1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-2016 The Khronos Group Inc.
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  */ /*!
20  * \file
21  * \brief
22  */ /*-------------------------------------------------------------------*/
23 
24 #include "esextcTessellationShaderMaxPatchVertices.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluDefs.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30 #include <cstddef>
31 #include <cstdlib>
32 
33 /* The test creates a patch with max patch vertices count size.
34  * The output from the tesselation stage is a single segment (2 vertices).
35  * Use this define when allocating/using the output TF buffer.
36  */
37 #define OUTPUT_VERTEX_COUNT 2
38 
39 namespace glcts
40 {
41 
42 /* Vertex Shader code */
43 const char *TessellationShaderMaxPatchVertices::m_vs_code = "${VERSION}\n"
44                                                             "\n"
45                                                             "${SHADER_IO_BLOCKS_ENABLE}\n"
46                                                             "\n"
47                                                             "precision highp float;\n"
48                                                             "\n"
49                                                             "layout(location = 0) in vec4  in_fv;\n"
50                                                             "layout(location = 1) in ivec4 in_iv;\n"
51                                                             "\n"
52                                                             "out Vertex\n"
53                                                             "{\n"
54                                                             "    ivec4 iv;\n"
55                                                             "    vec4  fv;\n"
56                                                             "} outVertex;\n"
57                                                             "\n"
58                                                             "void main()\n"
59                                                             "{\n"
60                                                             "    gl_Position  = in_fv;\n"
61                                                             "    outVertex.iv = in_iv;\n"
62                                                             "    outVertex.fv = in_fv;\n"
63                                                             "}\n";
64 
65 /* Tessellation Control Shader code (for case with explicit array size) */
66 const char *TessellationShaderMaxPatchVertices::m_tc_code =
67     "${VERSION}\n"
68     "\n"
69     "${TESSELLATION_SHADER_REQUIRE}\n"
70     "\n"
71     "precision highp float;\n"
72     "\n"
73     "in Vertex\n"
74     "{\n"
75     "    ivec4 iv;\n"
76     "    vec4  fv;\n"
77     "} inVertex[];\n"
78     "\n"
79     "layout(vertices = 2) out;\n" /* One segment only. */
80     "\n"
81     "out Vertex\n"
82     "{\n"
83     "    ivec4 iv;\n"
84     "    vec4  fv;\n"
85     "} outVertex[];\n"
86     "\n"
87     "void main()\n"
88     "{\n"
89     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
90     "    outVertex[gl_InvocationID].iv = ivec4(0);\n"
91     "    outVertex[gl_InvocationID].fv = vec4(0);\n"
92     "\n"
93     "    for (int i = 0; i < gl_PatchVerticesIn; i++)\n"
94     "    {\n"
95     "        outVertex[gl_InvocationID].iv += inVertex[i].iv;\n"
96     "        outVertex[gl_InvocationID].fv += inVertex[i].fv;\n"
97     "    }\n"
98     "\n"
99     "    gl_TessLevelInner[0] = 1.0;\n"
100     "    gl_TessLevelInner[1] = 1.0;\n"
101     "    gl_TessLevelOuter[0] = 1.0;\n"
102     "    gl_TessLevelOuter[1] = 1.0;\n"
103     "    gl_TessLevelOuter[2] = 1.0;\n"
104     "    gl_TessLevelOuter[3] = 1.0;\n"
105     "}\n";
106 
107 /* Tessellation Evaluation Shader code (for case */
108 const char *TessellationShaderMaxPatchVertices::m_te_code = "${VERSION}\n"
109                                                             "\n"
110                                                             "${TESSELLATION_SHADER_REQUIRE}\n"
111                                                             "\n"
112                                                             "precision highp float;\n"
113                                                             "\n"
114                                                             "layout (isolines, point_mode) in;\n"
115                                                             "\n"
116                                                             "in Vertex\n"
117                                                             "{\n"
118                                                             "    ivec4 iv;\n"
119                                                             "    vec4  fv;\n"
120                                                             "} inVertex[];\n"
121                                                             "\n"
122                                                             "out  vec4 result_fv;\n"
123                                                             "out ivec4 result_iv;\n"
124                                                             "\n"
125                                                             "void main()\n"
126                                                             "{\n"
127                                                             "    gl_Position = gl_in[0].gl_Position;\n"
128                                                             "    result_iv   = ivec4(0);\n"
129                                                             "    result_fv   = vec4(0.0);\n"
130                                                             "\n"
131                                                             "    for (int i = 0 ; i < gl_PatchVerticesIn; i++)\n"
132                                                             "    {\n"
133                                                             "        result_iv += inVertex[i].iv;\n"
134                                                             "        result_fv += inVertex[i].fv;\n"
135                                                             "    }\n"
136                                                             "}\n";
137 
138 /* Fragment Shader code */
139 const char *TessellationShaderMaxPatchVertices::m_fs_code = "${VERSION}\n"
140                                                             "\n"
141                                                             "void main()\n"
142                                                             "{\n"
143                                                             "}\n";
144 
145 /* Transform Feedback varyings */
146 const char *const TessellationShaderMaxPatchVertices::m_tf_varyings[] = {"result_fv", "result_iv"};
147 
148 /** Constructor
149  *
150  * @param context     Test context
151  * @param name        Test case's name
152  * @param description Test case's description
153  **/
TessellationShaderMaxPatchVertices(Context & context,const ExtParameters & extParams)154 TessellationShaderMaxPatchVertices::TessellationShaderMaxPatchVertices(Context &context, const ExtParameters &extParams)
155     : TestCaseBase(context, extParams, "max_patch_vertices",
156                    "Make sure it is possible to use up to gl_MaxPatchVertices vertices."
157                    " TCS must be able to correctly access all vertices in an input patch")
158     , m_bo_id_f_1(0)
159     , m_bo_id_f_2(0)
160     , m_bo_id_i_1(0)
161     , m_bo_id_i_2(0)
162     , m_fs_id(0)
163     , m_po_id_1(0)
164     , m_po_id_2(0)
165     , m_tc_id(0)
166     , m_te_id(0)
167     , m_tf_id_1(0)
168     , m_tf_id_2(0)
169     , m_vs_id(0)
170     , m_vao_id(0)
171     , m_gl_max_patch_vertices(0)
172     , m_patch_vertices_bo_f_id(0)
173     , m_patch_vertices_bo_i_id(0)
174     , m_patch_vertices_f(DE_NULL)
175     , m_patch_vertices_i(DE_NULL)
176 {
177 }
178 
179 /** Deinitializes all ES objects created for the test. */
deinit(void)180 void TessellationShaderMaxPatchVertices::deinit(void)
181 {
182     /* Deinitialize parent. */
183     TestCaseBase::deinit();
184 
185     if (!m_is_tessellation_shader_supported)
186     {
187         return;
188     }
189 
190     /* Dealocate input array of patch vertices. */
191     if (m_patch_vertices_f != DE_NULL)
192     {
193         free(m_patch_vertices_f);
194 
195         m_patch_vertices_f = DE_NULL;
196     }
197 
198     if (m_patch_vertices_i != DE_NULL)
199     {
200         free(m_patch_vertices_i);
201 
202         m_patch_vertices_i = DE_NULL;
203     }
204 
205     /* Retrieve ES entry-points. */
206     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
207 
208     /* Set back to default program */
209     gl.useProgram(0);
210 
211     /* Revert GL_PATCH_VERTICES_EXT value to the default setting */
212     gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, 3);
213 
214     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
215     {
216         /* Revert GL_PATCH_DEFAULT_INNER_LEVEL and GL_PATCH_DEFAULT_OUTER_LEVEL pname
217          * values to the default settings */
218         const float default_levels[] = {1.0f, 1.0f, 1.0f, 1.0f};
219 
220         gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, default_levels);
221         gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, default_levels);
222     }
223 
224     /* Disable vertex attribute arrays that may have been enabled for the test */
225     gl.disableVertexAttribArray(0);
226     gl.disableVertexAttribArray(1);
227 
228     /* Unbind buffer objects from TF binding points */
229     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* buffer */);
230     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, 0 /* buffer */);
231     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1 /* index */, 0 /* buffer */);
232 
233     /* Unbind transform feedback object */
234     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, 0 /* id */);
235 
236     /* Disable GL_RASTERIZER_DISCARD mode */
237     gl.disable(GL_RASTERIZER_DISCARD);
238 
239     /* Unbind vertex array object */
240     gl.bindVertexArray(0);
241 
242     /* Delete OpenGL objects */
243     if (m_bo_id_f_1 != 0)
244     {
245         gl.deleteBuffers(1, &m_bo_id_f_1);
246 
247         m_bo_id_f_1 = 0;
248     }
249 
250     if (m_bo_id_f_2 != 0)
251     {
252         gl.deleteBuffers(1, &m_bo_id_f_2);
253 
254         m_bo_id_f_2 = 0;
255     }
256 
257     if (m_bo_id_i_1 != 0)
258     {
259         gl.deleteBuffers(1, &m_bo_id_i_1);
260 
261         m_bo_id_i_1 = 0;
262     }
263 
264     if (m_bo_id_i_2 != 0)
265     {
266         gl.deleteBuffers(1, &m_bo_id_i_2);
267 
268         m_bo_id_i_2 = 0;
269     }
270 
271     if (m_patch_vertices_bo_f_id != 0)
272     {
273         gl.deleteBuffers(1, &m_patch_vertices_bo_f_id);
274 
275         m_patch_vertices_bo_f_id = 0;
276     }
277 
278     if (m_patch_vertices_bo_i_id != 0)
279     {
280         gl.deleteBuffers(1, &m_patch_vertices_bo_i_id);
281 
282         m_patch_vertices_bo_i_id = 0;
283     }
284 
285     if (m_vs_id != 0)
286     {
287         gl.deleteShader(m_vs_id);
288 
289         m_vs_id = 0;
290     }
291 
292     if (m_tc_id != 0)
293     {
294         gl.deleteShader(m_tc_id);
295 
296         m_tc_id = 0;
297     }
298 
299     if (m_te_id != 0)
300     {
301         gl.deleteShader(m_te_id);
302 
303         m_te_id = 0;
304     }
305 
306     if (m_fs_id != 0)
307     {
308         gl.deleteShader(m_fs_id);
309 
310         m_fs_id = 0;
311     }
312 
313     if (m_tf_id_1 != 0)
314     {
315         gl.deleteTransformFeedbacks(1, &m_tf_id_1);
316 
317         m_tf_id_1 = 0;
318     }
319 
320     if (m_tf_id_2 != 0)
321     {
322         gl.deleteTransformFeedbacks(1, &m_tf_id_2);
323 
324         m_tf_id_2 = 0;
325     }
326 
327     if (m_po_id_1 != 0)
328     {
329         gl.deleteProgram(m_po_id_1);
330 
331         m_po_id_1 = 0;
332     }
333 
334     if (m_po_id_2 != 0)
335     {
336         gl.deleteProgram(m_po_id_2);
337 
338         m_po_id_2 = 0;
339     }
340 
341     if (m_vao_id != 0)
342     {
343         gl.deleteVertexArrays(1, &m_vao_id);
344 
345         m_vao_id = 0;
346     }
347 }
348 
349 /** Initializes all ES objects and reference values for the test. */
initTest(void)350 void TessellationShaderMaxPatchVertices::initTest(void)
351 {
352     /* This test runs for two cases:
353      *
354      * 1) The patch size is explicitly defined to be equal to gl_MaxPatchVertices.
355      *    (The Tessellation Control Shader gets 32 vertices, then it access them
356      *    and it outputs 2 vertices to Tessllation Evaluation Shader. Next Tessllation
357      *    Evaluation Shader sends 1 segment of an isoline  to the output).
358      * 2) The patch size is implicitly defined to be equal to gl_MaxPatchVertices.
359      *    (There is no Tessellation Control Shader. Tessllation Evaluation Shader
360      *    gets 32 vertices, then it access them. Next (gl_MaxPatchVertices-1) segments
361      *    of the isoline are send to the output.)
362      */
363 
364     /* Retrieve ES entry/state points. */
365     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
366 
367     /* Initialize vertex array object */
368     gl.genVertexArrays(1, &m_vao_id);
369     GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
370 
371     gl.bindVertexArray(m_vao_id);
372     GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
373 
374     /* Query GL_MAX_PATCH_VERTICES_EXT value */
375     gl.getIntegerv(m_glExtTokens.MAX_PATCH_VERTICES, &m_gl_max_patch_vertices);
376     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed for GL_MAX_PATCH_VERTICES_EXT pname!");
377 
378     /* Set maximum number of vertices in the patch. */
379     gl.patchParameteri(m_glExtTokens.PATCH_VERTICES, m_gl_max_patch_vertices);
380     GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameteriEXT() failed for GL_PATCH_VERTICES_EXT pname!");
381 
382     /* Build programs */
383     initProgramObjects();
384 
385     /* Initialize tessellation buffers */
386     initTransformFeedbackBufferObjects();
387 
388     /* Initialize input vertices */
389     initVertexBufferObjects();
390 
391     /* Reference values setup */
392     initReferenceValues();
393 }
394 
395 /** Initializes buffer objects for the test. */
initVertexBufferObjects(void)396 void TessellationShaderMaxPatchVertices::initVertexBufferObjects(void)
397 {
398     /* Retrieve ES entry/state points. */
399     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
400 
401     /* Input patch vertices buffer setup. */
402     m_patch_vertices_f = (glw::GLfloat *)malloc(m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLfloat));
403 
404     if (m_patch_vertices_f == DE_NULL)
405     {
406         TCU_FAIL("Memory allocation failed!");
407     }
408 
409     m_patch_vertices_i = (glw::GLint *)malloc(m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLint));
410 
411     if (m_patch_vertices_i == DE_NULL)
412     {
413         TCU_FAIL("Memory allocation failed!");
414     }
415 
416     for (int i = 0; i < m_gl_max_patch_vertices * 4 /* components */; i += 4 /* components */)
417     {
418         m_patch_vertices_f[i]     = 1.0f;
419         m_patch_vertices_f[i + 1] = 2.0f;
420         m_patch_vertices_f[i + 2] = 3.0f;
421         m_patch_vertices_f[i + 3] = 4.0f;
422 
423         m_patch_vertices_i[i]     = 1;
424         m_patch_vertices_i[i + 1] = 2;
425         m_patch_vertices_i[i + 2] = 3;
426         m_patch_vertices_i[i + 3] = 4;
427     }
428 
429     /* Vec4 vertex attribute array setup. */
430     gl.genBuffers(1, &m_patch_vertices_bo_f_id);
431     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed!");
432 
433     gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_vertices_bo_f_id);
434     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
435 
436     gl.bufferData(GL_ARRAY_BUFFER, m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLfloat),
437                   m_patch_vertices_f, GL_STATIC_DRAW);
438     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed!");
439 
440     gl.vertexAttribPointer(0,        /* index */
441                            4,        /* size */
442                            GL_FLOAT, /* type */
443                            GL_FALSE, /* normalized */
444                            0,        /* stride */
445                            0);       /* pointer */
446     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer(fv) failed!");
447 
448     gl.enableVertexAttribArray(0);
449     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray(fv) failed!");
450 
451     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
452 
453     /* Ivec4 vertex attribute array setup. */
454     gl.genBuffers(1, &m_patch_vertices_bo_i_id);
455     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers(ARRAY_BUFFER) failed!");
456 
457     gl.bindBuffer(GL_ARRAY_BUFFER, m_patch_vertices_bo_i_id);
458     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer(ARRAY_BUFFER) failed!");
459 
460     gl.bufferData(GL_ARRAY_BUFFER, m_gl_max_patch_vertices * 4 /* components */ * sizeof(glw::GLint),
461                   m_patch_vertices_i, GL_STATIC_DRAW);
462     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData(ARRAY_BUFFER) failed!");
463 
464     gl.vertexAttribIPointer(1,         /* index */
465                             4,         /* size */
466                             GL_INT, 0, /* stride */
467                             0);        /* pointer */
468     GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer(iv) failed!");
469 
470     gl.enableVertexAttribArray(1);
471     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray(iv) failed!");
472 
473     gl.bindBuffer(GL_ARRAY_BUFFER, 0);
474     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
475 }
476 
477 /** Initializes buffer objects for the test. */
initTransformFeedbackBufferObjects(void)478 void TessellationShaderMaxPatchVertices::initTransformFeedbackBufferObjects(void)
479 {
480     /* Retrieve ES entry/state points. */
481     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
482 
483     /* Creating Transform Feedback buffer objects. */
484     gl.genBuffers(1, &m_bo_id_f_1);
485     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
486 
487     gl.genBuffers(1, &m_bo_id_f_2);
488     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
489 
490     gl.genBuffers(1, &m_bo_id_i_1);
491     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
492 
493     gl.genBuffers(1, &m_bo_id_i_2);
494     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers() failed");
495 
496     /* Transform feedback buffers for case 1*/
497     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1);
498     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
499 
500     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_1);
501     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
502 
503     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
504                   ((sizeof(glw::GLfloat)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
505                   GL_STATIC_DRAW);
506     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
507 
508     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_1);
509     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
510 
511     gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
512                   ((sizeof(glw::GLint)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
513                   GL_STATIC_DRAW);
514     GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
515 
516     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
517     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback(0) failed");
518 
519     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
520     {
521         /* Transform feedback buffers for case 2*/
522         gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2);
523         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
524 
525         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_2);
526         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
527 
528         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
529                       ((sizeof(glw::GLfloat)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
530                       GL_STATIC_DRAW);
531         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
532 
533         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_2);
534         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
535 
536         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
537                       ((sizeof(glw::GLint)) * 4 /* components */ * OUTPUT_VERTEX_COUNT /* vertices */), DE_NULL,
538                       GL_STATIC_DRAW);
539         GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData() failed");
540 
541         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, 0);
542         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback(0) failed");
543 
544         gl.transformFeedbackVaryings(m_po_id_2, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS);
545         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
546     }
547 }
548 
549 /** Initializes program objects for the test. */
initProgramObjects(void)550 void TessellationShaderMaxPatchVertices::initProgramObjects(void)
551 {
552     /* Retrieve ES entry/state points. */
553     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
554 
555     /* Create and configure shader objects. */
556     m_po_id_1 = gl.createProgram();
557     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
558 
559     m_po_id_2 = gl.createProgram();
560     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed!");
561 
562     /* Creating Transform Feedback objects. */
563     gl.genTransformFeedbacks(1, &m_tf_id_1);
564     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() failed!");
565 
566     gl.genTransformFeedbacks(1, &m_tf_id_2);
567     GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks() failed!");
568 
569     /* Create and configure shader objects. */
570     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
571     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader(VERTEX_SHADER) failed!");
572 
573     m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
574     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!");
575 
576     m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
577     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!");
578 
579     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
580     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed!");
581 
582     /* Transform Feedback setup case 1 (explicit arrays).*/
583     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1);
584     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
585 
586     gl.transformFeedbackVaryings(m_po_id_1, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS);
587     GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
588 
589     /* Build the program object case 1 (explicit arrays).*/
590     if (!buildProgram(m_po_id_1, m_vs_id, 1, &m_vs_code, m_tc_id, 1, &m_tc_code, m_te_id, 1, &m_te_code, m_fs_id, 1,
591                       &m_fs_code))
592     {
593         TCU_FAIL("Program linking failed!");
594     }
595 
596     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
597     {
598         /* Transform Feedback setup case 2 (implicit arrays).*/
599         gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2);
600         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
601 
602         gl.transformFeedbackVaryings(m_po_id_2, 2 /* count */, m_tf_varyings, GL_SEPARATE_ATTRIBS);
603         GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings() failed!");
604 
605         /* Build the program object case 2 (implicit arrays). */
606         if (!buildProgram(m_po_id_2, m_vs_id, 1, &m_vs_code, m_te_id, 1, &m_te_code, m_fs_id, 1, &m_fs_code))
607         {
608             TCU_FAIL("Program linking failed!");
609         }
610     }
611 }
612 
613 /** Initializes reference values for the test. */
initReferenceValues(void)614 void TessellationShaderMaxPatchVertices::initReferenceValues(void)
615 {
616     /* Reference values setup. */
617     m_ref_fv_case_1[0] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 1.0f);
618     m_ref_fv_case_1[1] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 2.0f);
619     m_ref_fv_case_1[2] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 3.0f);
620     m_ref_fv_case_1[3] = ((glw::GLfloat)(m_gl_max_patch_vertices * 2) * 4.0f);
621 
622     m_ref_iv_case_1[0] = (m_gl_max_patch_vertices * 2 * 1);
623     m_ref_iv_case_1[1] = (m_gl_max_patch_vertices * 2 * 2);
624     m_ref_iv_case_1[2] = (m_gl_max_patch_vertices * 2 * 3);
625     m_ref_iv_case_1[3] = (m_gl_max_patch_vertices * 2 * 4);
626 
627     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
628     {
629         m_ref_fv_case_2[0] = ((glw::GLfloat)m_gl_max_patch_vertices * 1.0f);
630         m_ref_fv_case_2[1] = ((glw::GLfloat)m_gl_max_patch_vertices * 2.0f);
631         m_ref_fv_case_2[2] = ((glw::GLfloat)m_gl_max_patch_vertices * 3.0f);
632         m_ref_fv_case_2[3] = ((glw::GLfloat)m_gl_max_patch_vertices * 4.0f);
633 
634         m_ref_iv_case_2[0] = (m_gl_max_patch_vertices * 1);
635         m_ref_iv_case_2[1] = (m_gl_max_patch_vertices * 2);
636         m_ref_iv_case_2[2] = (m_gl_max_patch_vertices * 3);
637         m_ref_iv_case_2[3] = (m_gl_max_patch_vertices * 4);
638     }
639 }
640 
641 /** Compares values of vec4 results with the reference data.
642  *
643  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed.
644  *
645  *  Note the function throws exception should an error occur!
646  *
647  *  @param description Test case's description.
648  *  @param ref_fv      Reference value.
649  *
650  *  @return true       if test passed;
651  *          false      if test failed.
652  **/
compareResults(const char * description,glw::GLfloat ref_fv[4])653 bool TessellationShaderMaxPatchVertices::compareResults(const char *description, glw::GLfloat ref_fv[4])
654 {
655     /* Retrieve ES entry/state points. */
656     const glw::Functions &gl         = m_context.getRenderContext().getFunctions();
657     const glw::GLfloat *resultFloats = DE_NULL;
658 
659     resultFloats = (const glw::GLfloat *)gl.mapBufferRange(
660         GL_TRANSFORM_FEEDBACK_BUFFER, 0, /* offset */
661         (sizeof(glw::GLfloat) /* GLfloat size */ * 4 /* components */ * OUTPUT_VERTEX_COUNT), GL_MAP_READ_BIT);
662     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(floats) failed");
663 
664     /* Comparison of vec4. */
665     const glw::GLfloat epsilon = (glw::GLfloat)1e-5f;
666     bool test_failed           = false;
667 
668     for (int i = 0; i < 4 /* components */; i++)
669     {
670         if (de::abs(resultFloats[i] - ref_fv[i]) > epsilon)
671         {
672             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
673 
674             m_testCtx.getLog() << tcu::TestLog::Message << description << " captured results "
675                                << "vec4(" << resultFloats[0] << ", " << resultFloats[1] << ", " << resultFloats[2]
676                                << ", " << resultFloats[3] << ") "
677                                << "are different from the expected values "
678                                << "vec4(" << ref_fv[0] << ", " << ref_fv[1] << ", " << ref_fv[2] << ", " << ref_fv[3]
679                                << ")." << tcu::TestLog::EndMessage;
680 
681             test_failed = true;
682             break;
683         }
684     }
685 
686     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
687     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!");
688 
689     return !test_failed;
690 }
691 
692 /** Compares values of ivec4 results with the reference data.
693  *
694  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed.
695  *
696  *  Note the function throws exception should an error occur!
697  *
698  *  @param description   Test case's description.
699  *  @param ref_iv        Reference value.
700  *
701  *  @return true         if test passed.
702  *          false        if test failed.
703  **/
compareResults(const char * description,glw::GLint ref_iv[4])704 bool TessellationShaderMaxPatchVertices::compareResults(const char *description, glw::GLint ref_iv[4])
705 {
706     /* Retrieve ES entry/state points. */
707     const glw::Functions &gl     = m_context.getRenderContext().getFunctions();
708     const glw::GLint *resultInts = DE_NULL;
709 
710     resultInts = (const glw::GLint *)gl.mapBufferRange(
711         GL_TRANSFORM_FEEDBACK_BUFFER, 0,
712         (sizeof(glw::GLint) /* GLfloat size */ * 4 /* components */ * OUTPUT_VERTEX_COUNT), GL_MAP_READ_BIT);
713     GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange(ints) failed");
714 
715     bool test_failed = false;
716 
717     /* Comparison of ivec4. */
718     for (int i = 0; i < 4 /* components */; i++)
719     {
720         if (resultInts[i] != ref_iv[i])
721         {
722             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
723 
724             m_testCtx.getLog() << tcu::TestLog::Message << description << " captured results ivec4(" << resultInts[0]
725                                << ", " << resultInts[1] << ", " << resultInts[2] << ", " << resultInts[3] << ") "
726                                << "are different from the expected values ivec4(" << ref_iv[0] << ", " << ref_iv[1]
727                                << ", " << ref_iv[2] << ", " << ref_iv[3] << ")." << tcu::TestLog::EndMessage;
728 
729             test_failed = true;
730             break;
731         }
732     }
733 
734     gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
735     GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer() failed!");
736 
737     return !test_failed;
738 }
739 
740 /** Executes the test.
741  *
742  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
743  *
744  *  Note the function throws exception should an error occur!
745  *
746  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
747  **/
iterate(void)748 tcu::TestNode::IterateResult TessellationShaderMaxPatchVertices::iterate(void)
749 {
750     /* Skip if required extensions are not supported. */
751     if (!m_is_tessellation_shader_supported)
752     {
753         throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
754     }
755 
756     /* Retrieve ES entry/state points. */
757     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
758 
759     /* Initialization */
760     initTest();
761 
762     /* Render setup case 1. */
763     gl.useProgram(m_po_id_1);
764     GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
765 
766     gl.enable(GL_RASTERIZER_DISCARD);
767     GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable(RASTERIZER_DISCARD) failed!");
768 
769     gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_1);
770     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
771 
772     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_f_1);
773     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
774 
775     gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_i_1);
776     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
777 
778     /* Rendering case 1 with transform feedback.*/
779     gl.beginTransformFeedback(GL_POINTS);
780     GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback() failed");
781 
782     gl.drawArrays(m_glExtTokens.PATCHES, 0, m_gl_max_patch_vertices);
783     GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
784 
785     gl.endTransformFeedback();
786     GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
787 
788     /* Compare vec4 results from transform feedback for case 1. */
789     bool test_passed = true;
790 
791     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_1);
792     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
793 
794     test_passed &= compareResults("Case 1 (explicit arrays)", m_ref_fv_case_1);
795 
796     /* Compare ivec4 results from transform feedback for case 2. */
797     gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_1);
798     GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
799 
800     test_passed &= compareResults("Case 1 (explicit arrays)", m_ref_iv_case_1);
801 
802     // Case 2 tests with no TCS (default TCS is expected to be used).
803     // Since this is not allowed by ES 3.1, just skip it.
804     // Leaving the code for Desktop
805     if (!glu::isContextTypeES(m_context.getRenderContext().getType()))
806     {
807         /* Set up rendering for case 2. */
808         gl.useProgram(m_po_id_2);
809         GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram() failed!");
810 
811         gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id_2);
812         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback() failed!");
813 
814         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0 /* index */, m_bo_id_f_2);
815         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
816 
817         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1 /* index */, m_bo_id_i_2);
818         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange() failed!");
819 
820         /* Tessellation Control Levels setup. */
821         const glw::GLfloat inner[] = {1.0, 1.0};
822         const glw::GLfloat outer[] = {1.0, 1.0, 1.0, 1.0};
823 
824         gl.patchParameterfv(GL_PATCH_DEFAULT_OUTER_LEVEL, outer);
825         GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() failed!");
826 
827         gl.patchParameterfv(GL_PATCH_DEFAULT_INNER_LEVEL, inner);
828         GLU_EXPECT_NO_ERROR(gl.getError(), "glPatchParameterfv() failed!");
829 
830         /* Rendering case 2 with transform feedback. */
831         gl.beginTransformFeedback(GL_POINTS);
832         GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback(GL_POINTS) failed");
833 
834         gl.drawArrays(GL_PATCHES, 0, m_gl_max_patch_vertices);
835         GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays() failed");
836 
837         gl.endTransformFeedback();
838         GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback() failed");
839 
840         /* Compare vec4 results from transform feedback for case 2. */
841         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_f_2);
842         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
843 
844         test_passed &= compareResults("Case 2 (implicit arrays)", m_ref_fv_case_2);
845 
846         /* Compare ivec4 results from transform feedback for case 2. */
847         gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_i_2);
848         GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer() failed!");
849 
850         test_passed &= compareResults("Case 2 (implicit arrays)", m_ref_iv_case_2);
851     }
852     /* All done */
853     if (test_passed)
854     {
855         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
856     }
857 
858     return STOP;
859 }
860 
861 } /* namespace glcts */
862