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