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 "esextcTessellationShaderProperties.hpp"
25 #include "gluContextInfo.hpp"
26 #include "gluDefs.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30 #include <cmath>
31 #include <cstring>
32 
33 namespace glcts
34 {
35 /** Constructor
36  *
37  * @param context Test context
38  **/
TessellationShaderPropertiesDefaultContextWideValues(Context & context,const ExtParameters & extParams)39 TessellationShaderPropertiesDefaultContextWideValues::TessellationShaderPropertiesDefaultContextWideValues(
40     Context &context, const ExtParameters &extParams)
41     : TestCaseBase(context, extParams, "default_values_of_context_wide_properties",
42                    "Verifies default values of context-wide tessellation stage properties")
43 {
44     /* Left blank on purpose */
45 }
46 
47 /** Executes the test.
48  *
49  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
50  *
51  *  Note the function throws exception should an error occur!
52  *
53  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
54  **/
iterate(void)55 tcu::TestNode::IterateResult TessellationShaderPropertiesDefaultContextWideValues::iterate(void)
56 {
57     /* Do not execute if required extensions are not supported. */
58     if (!m_is_tessellation_shader_supported)
59     {
60         throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
61     }
62 
63     /* Iterate through all context-wide properties and compare expected values
64      * against the reference ones
65      */
66     const float epsilon      = (float)1e-5;
67     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
68 
69     const glw::GLint property_value_data[] = {/* pname */ /* n components */ /* default value */
70                                               static_cast<glw::GLint>(m_glExtTokens.PATCH_VERTICES), 1, 3,
71                                               /* The following values are only applicable to Desktop OpenGL. */
72                                               GL_PATCH_DEFAULT_OUTER_LEVEL, 4, 1, GL_PATCH_DEFAULT_INNER_LEVEL, 2, 1};
73 
74     const unsigned int n_properties = (glu::isContextTypeES(m_context.getRenderContext().getType())) ? 1 : 3;
75 
76     for (unsigned int n_property = 0; n_property < n_properties; ++n_property)
77     {
78         glw::GLboolean bool_value[4] = {GL_FALSE};
79         glw::GLfloat float_value[4]  = {0.0f};
80         glw::GLint int_value[4]      = {0};
81 
82         glw::GLenum pname         = property_value_data[n_property * 3 + 0];
83         glw::GLint n_components   = property_value_data[n_property * 3 + 1];
84         glw::GLint expected_value = property_value_data[n_property * 3 + 2];
85 
86         /* Call all relevant getters */
87         gl.getBooleanv(pname, bool_value);
88         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetBooleanv() failed.");
89 
90         gl.getFloatv(pname, float_value);
91         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv() failed.");
92 
93         gl.getIntegerv(pname, int_value);
94         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv() failed.");
95 
96         /* Compare retrieved vector value components against expected value */
97         glw::GLboolean expected_bool_value[4] = {
98             (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE,
99             (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE,
100             (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE,
101             (expected_value != 0) ? (glw::GLboolean)GL_TRUE : (glw::GLboolean)GL_FALSE};
102         glw::GLint expected_int_value[4] = {expected_value, expected_value, expected_value, expected_value};
103 
104         if (memcmp(expected_bool_value, bool_value, sizeof(bool) * n_components) != 0)
105         {
106             m_testCtx.getLog() << tcu::TestLog::Message << "glGetBooleanv() called for pname " << pname
107                                << " reported invalid value." << tcu::TestLog::EndMessage;
108 
109             TCU_FAIL("Invalid value reported by glGetBooleanv()");
110         }
111 
112         if (memcmp(expected_int_value, int_value, sizeof(int) * n_components) != 0)
113         {
114             m_testCtx.getLog() << tcu::TestLog::Message << "glGetIntegerv() called for pname " << pname
115                                << " reported invalid value." << tcu::TestLog::EndMessage;
116 
117             TCU_FAIL("Invalid value reported by glGetIntegerv()");
118         }
119 
120         if ((n_components >= 1 && de::abs(float_value[0] - (float)expected_value) > epsilon) ||
121             (n_components >= 2 && de::abs(float_value[1] - (float)expected_value) > epsilon) ||
122             (n_components >= 3 && de::abs(float_value[2] - (float)expected_value) > epsilon) ||
123             (n_components >= 4 && de::abs(float_value[3] - (float)expected_value) > epsilon))
124         {
125             m_testCtx.getLog() << tcu::TestLog::Message << "glGetFloatv() called for pname " << pname
126                                << " reported invalid value." << tcu::TestLog::EndMessage;
127 
128             TCU_FAIL("Invalid value reported by glGetFloatv()");
129         }
130     } /* for (all properties) */
131 
132     /* All done */
133     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
134     return STOP;
135 }
136 
137 /** Constructor
138  *
139  * @param context Test context
140  **/
TessellationShaderPropertiesProgramObject(Context & context,const ExtParameters & extParams)141 TessellationShaderPropertiesProgramObject::TessellationShaderPropertiesProgramObject(Context &context,
142                                                                                      const ExtParameters &extParams)
143     : TestCaseBase(context, extParams, "program_object_properties",
144                    "Verifies tessellation-specific properties of program objects are reported correctly.")
145     , m_fs_id(0)
146     , m_po_id(0)
147     , m_tc_id(0)
148     , m_te_id(0)
149     , m_vs_id(0)
150 {
151     /* Left blank on purpose */
152 }
153 
154 /** Deinitializes ES objects created for the test */
deinit(void)155 void TessellationShaderPropertiesProgramObject::deinit(void)
156 {
157     /* Call base class' deinit() */
158     TestCaseBase::deinit();
159 
160     /* Release any ES objects created */
161     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
162 
163     if (m_fs_id != 0)
164     {
165         gl.deleteShader(m_fs_id);
166 
167         m_fs_id = 0;
168     }
169 
170     if (m_po_id != 0)
171     {
172         gl.deleteProgram(m_po_id);
173 
174         m_po_id = 0;
175     }
176 
177     if (m_tc_id != 0)
178     {
179         gl.deleteShader(m_tc_id);
180 
181         m_tc_id = 0;
182     }
183 
184     if (m_te_id != 0)
185     {
186         gl.deleteShader(m_te_id);
187 
188         m_te_id = 0;
189     }
190 
191     if (m_vs_id != 0)
192     {
193         gl.deleteShader(m_vs_id);
194 
195         m_vs_id = 0;
196     }
197 }
198 
199 /** Initializes ES objects necessary to execute the test */
initTest(void)200 void TessellationShaderPropertiesProgramObject::initTest(void)
201 {
202     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
203 
204     /* Do not execute if required extension is not supported */
205     if (!m_is_tessellation_shader_supported)
206     {
207         return;
208     }
209 
210     /* Generate all objects */
211     m_po_id = gl.createProgram();
212     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram() failed");
213 
214     m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
215     m_tc_id = gl.createShader(m_glExtTokens.TESS_CONTROL_SHADER);
216     m_te_id = gl.createShader(m_glExtTokens.TESS_EVALUATION_SHADER);
217     m_vs_id = gl.createShader(GL_VERTEX_SHADER);
218     GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader() failed");
219 
220     /* Attach the shader to the program object */
221     gl.attachShader(m_po_id, m_fs_id);
222     gl.attachShader(m_po_id, m_tc_id);
223     gl.attachShader(m_po_id, m_te_id);
224     gl.attachShader(m_po_id, m_vs_id);
225     GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader() failed");
226 
227     /* Since this test does not care much about fragment & vertex shaders, set
228      * their bodies and compile these shaders now */
229     const char *fs_body = "${VERSION}\n"
230                           "\n"
231                           "void main()\n"
232                           "{\n"
233                           "}\n";
234 
235     const char *vs_body = "${VERSION}\n"
236                           "\n"
237                           "void main()\n"
238                           "{\n"
239                           "}\n";
240 
241     glw::GLint fs_compile_status = GL_FALSE;
242     glw::GLint vs_compile_status = GL_FALSE;
243 
244     shaderSourceSpecialized(m_fs_id, 1 /* count */, &fs_body);
245     shaderSourceSpecialized(m_vs_id, 1 /* count */, &vs_body);
246     GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed");
247 
248     gl.compileShader(m_fs_id);
249     gl.compileShader(m_vs_id);
250     GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
251 
252     gl.getShaderiv(m_fs_id, GL_COMPILE_STATUS, &fs_compile_status);
253     gl.getShaderiv(m_vs_id, GL_COMPILE_STATUS, &vs_compile_status);
254     GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
255 
256     if (fs_compile_status != GL_TRUE)
257     {
258         TCU_FAIL("Could not compile fragment shader");
259     }
260 
261     if (vs_compile_status != GL_TRUE)
262     {
263         TCU_FAIL("Could not compile vertex shader");
264     }
265 }
266 
267 /** Executes the test.
268  *
269  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
270  *
271  *  Note the function throws exception should an error occur!
272  *
273  *  @return STOP if the test has finished, CONTINUE to indicate iterate() should be called once again.
274  **/
iterate(void)275 tcu::TestNode::IterateResult TessellationShaderPropertiesProgramObject::iterate(void)
276 {
277     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
278 
279     /* Do not execute if required extensions are not supported. */
280     if (!m_is_tessellation_shader_supported)
281     {
282         throw tcu::NotSupportedError(TESSELLATION_SHADER_EXTENSION_NOT_SUPPORTED);
283     }
284 
285     /* Initialize ES test objects */
286     initTest();
287 
288     /* Test 1: Default values. Values as per spec, define as little qualifiers as possible */
289     _test_descriptor test_1;
290 
291     test_1.expected_control_output_vertices_value = 4;
292     test_1.expected_gen_mode_value                = m_glExtTokens.QUADS;
293     test_1.expected_gen_point_mode_value          = GL_FALSE;
294     test_1.expected_gen_spacing_value             = GL_EQUAL;
295     test_1.expected_gen_vertex_order_value        = GL_CCW;
296     test_1.tc_body                                = "${VERSION}\n"
297                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
298                                                     "\n"
299                                                     "layout(vertices=4) out;\n"
300                                                     "\n"
301                                                     "void main()\n"
302                                                     "{\n"
303                                                     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
304                                                     "}\n";
305     test_1.te_body                                = "${VERSION}\n"
306                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
307                                                     "\n"
308                                                     "layout(quads) in;\n"
309                                                     "\n"
310                                                     "void main()\n"
311                                                     "{\n"
312                                                     "    gl_Position = gl_in[0].gl_Position;\n"
313                                                     "}\n";
314 
315     /* Test 2: 16 vertices per patch + isolines + fractional_even_spacing + cw combination */
316     _test_descriptor test_2;
317 
318     test_2.expected_control_output_vertices_value = 16;
319     test_2.expected_gen_mode_value                = m_glExtTokens.ISOLINES;
320     test_2.expected_gen_point_mode_value          = GL_FALSE;
321     test_2.expected_gen_spacing_value             = m_glExtTokens.FRACTIONAL_EVEN;
322     test_2.expected_gen_vertex_order_value        = GL_CW;
323     test_2.tc_body                                = "${VERSION}\n"
324                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
325                                                     "\n"
326                                                     "layout(vertices=16) out;\n"
327                                                     "\n"
328                                                     "void main()\n"
329                                                     "{\n"
330                                                     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
331                                                     "}\n";
332     test_2.te_body                                = "${VERSION}\n"
333                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
334                                                     "\n"
335                                                     "layout(isolines, fractional_even_spacing, cw) in;\n"
336                                                     "\n"
337                                                     "void main()\n"
338                                                     "{\n"
339                                                     "    gl_Position = gl_in[0].gl_Position;\n"
340                                                     "}\n";
341 
342     /* Test 3: 32 vertices per patch + triangles + fractional_odd_spacing + ccw combination + point mode*/
343     _test_descriptor test_3;
344 
345     test_3.expected_control_output_vertices_value = 32;
346     test_3.expected_gen_mode_value                = GL_TRIANGLES;
347     test_3.expected_gen_point_mode_value          = GL_TRUE;
348     test_3.expected_gen_spacing_value             = m_glExtTokens.FRACTIONAL_ODD;
349     test_3.expected_gen_vertex_order_value        = GL_CCW;
350     test_3.tc_body                                = "${VERSION}\n"
351                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
352                                                     "\n"
353                                                     "layout(vertices=32) out;\n"
354                                                     "\n"
355                                                     "void main()\n"
356                                                     "{\n"
357                                                     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
358                                                     "}\n";
359     test_3.te_body                                = "${VERSION}\n"
360                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
361                                                     "\n"
362                                                     "layout(triangles, fractional_odd_spacing, ccw, point_mode) in;\n"
363                                                     "\n"
364                                                     "void main()\n"
365                                                     "{\n"
366                                                     "    gl_Position = gl_in[0].gl_Position;\n"
367                                                     "}\n";
368 
369     /* Test 4: 8 vertices per patch + quads + equal_spacing + ccw combination + point mode*/
370     _test_descriptor test_4;
371 
372     test_4.expected_control_output_vertices_value = 8;
373     test_4.expected_gen_mode_value                = m_glExtTokens.QUADS;
374     test_4.expected_gen_point_mode_value          = GL_TRUE;
375     test_4.expected_gen_spacing_value             = GL_EQUAL;
376     test_4.expected_gen_vertex_order_value        = GL_CCW;
377     test_4.tc_body                                = "${VERSION}\n"
378                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
379                                                     "\n"
380                                                     "layout(vertices=8) out;\n"
381                                                     "\n"
382                                                     "void main()\n"
383                                                     "{\n"
384                                                     "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
385                                                     "}\n";
386     test_4.te_body                                = "${VERSION}\n"
387                                                     "${TESSELLATION_SHADER_REQUIRE}\n"
388                                                     "\n"
389                                                     "layout(quads, equal_spacing, ccw, point_mode) in;\n"
390                                                     "\n"
391                                                     "void main()\n"
392                                                     "{\n"
393                                                     "    gl_Position = gl_in[0].gl_Position;\n"
394                                                     "}\n";
395 
396     /* Store all tests in a single vector */
397     _tests tests;
398 
399     tests.push_back(test_1);
400     tests.push_back(test_2);
401     tests.push_back(test_3);
402     tests.push_back(test_4);
403 
404     /* Iterate through all the tests and verify the values reported */
405     for (_tests_const_iterator test_iterator = tests.begin(); test_iterator != tests.end(); test_iterator++)
406     {
407         const _test_descriptor &test = *test_iterator;
408 
409         /* Set tessellation control & evaluation shader bodies. */
410         shaderSourceSpecialized(m_tc_id, 1 /* count */, &test.tc_body);
411         shaderSourceSpecialized(m_te_id, 1 /* count */, &test.te_body);
412 
413         GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource() failed");
414 
415         /* Compile the shaders */
416         gl.compileShader(m_tc_id);
417         gl.compileShader(m_te_id);
418 
419         GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader() failed");
420 
421         /* Make sure the shaders compiled */
422         glw::GLint tc_compile_status = GL_FALSE;
423         glw::GLint te_compile_status = GL_FALSE;
424 
425         gl.getShaderiv(m_tc_id, GL_COMPILE_STATUS, &tc_compile_status);
426         gl.getShaderiv(m_te_id, GL_COMPILE_STATUS, &te_compile_status);
427 
428         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv() failed");
429 
430         if (tc_compile_status != GL_TRUE)
431         {
432             TCU_FAIL("Could not compile tessellation control shader");
433         }
434 
435         if (te_compile_status != GL_TRUE)
436         {
437             TCU_FAIL("Could not compile tessellation evaluation shader");
438         }
439 
440         /* Try to link the program object */
441         glw::GLint link_status = GL_FALSE;
442 
443         gl.linkProgram(m_po_id);
444         GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram() failed");
445 
446         gl.getProgramiv(m_po_id, GL_LINK_STATUS, &link_status);
447         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() failed");
448 
449         if (link_status != GL_TRUE)
450         {
451             TCU_FAIL("Program linking failed");
452         }
453 
454         /* Query the tessellation properties of the program object and make sure
455          * the values reported are valid */
456         glw::GLint control_output_vertices_value = 0;
457         glw::GLint gen_mode_value                = GL_NONE;
458         glw::GLint gen_spacing_value             = GL_NONE;
459         glw::GLint gen_vertex_order_value        = GL_NONE;
460         glw::GLint gen_point_mode_value          = GL_NONE;
461 
462         gl.getProgramiv(m_po_id, m_glExtTokens.TESS_CONTROL_OUTPUT_VERTICES, &control_output_vertices_value);
463         gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_MODE, &gen_mode_value);
464         gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_SPACING, &gen_spacing_value);
465         gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_POINT_MODE, &gen_point_mode_value);
466         gl.getProgramiv(m_po_id, m_glExtTokens.TESS_GEN_VERTEX_ORDER, &gen_vertex_order_value);
467         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv() for tessellation-specific properties failed.");
468 
469         if (control_output_vertices_value != test.expected_control_output_vertices_value)
470         {
471             m_testCtx.getLog() << tcu::TestLog::Message
472                                << "Invalid value reported for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT property; "
473                                << " expected: " << test.expected_control_output_vertices_value
474                                << ", retrieved: " << control_output_vertices_value << tcu::TestLog::EndMessage;
475 
476             TCU_FAIL("Invalid value reported for GL_TESS_CONTROL_OUTPUT_VERTICES_EXT property.");
477         }
478 
479         if ((glw::GLuint)gen_mode_value != test.expected_gen_mode_value)
480         {
481             m_testCtx.getLog() << tcu::TestLog::Message << "Invalid value reported for GL_TESS_GEN_MODE_EXT property; "
482                                << " expected: " << test.expected_gen_mode_value << ", retrieved: " << gen_mode_value
483                                << tcu::TestLog::EndMessage;
484 
485             TCU_FAIL("Invalid value reported for GL_TESS_GEN_MODE_EXT property.");
486         }
487 
488         if ((glw::GLuint)gen_spacing_value != test.expected_gen_spacing_value)
489         {
490             m_testCtx.getLog() << tcu::TestLog::Message
491                                << "Invalid value reported for GL_TESS_GEN_SPACING_EXT property; "
492                                << " expected: " << test.expected_gen_spacing_value
493                                << ", retrieved: " << gen_spacing_value << tcu::TestLog::EndMessage;
494 
495             TCU_FAIL("Invalid value reported for GL_TESS_GEN_SPACING_EXT property.");
496         }
497 
498         if ((glw::GLuint)gen_point_mode_value != test.expected_gen_point_mode_value)
499         {
500             m_testCtx.getLog() << tcu::TestLog::Message
501                                << "Invalid value reported for GL_TESS_GEN_POINT_MODE_EXT property; "
502                                << " expected: " << test.expected_gen_point_mode_value
503                                << ", retrieved: " << gen_point_mode_value << tcu::TestLog::EndMessage;
504 
505             TCU_FAIL("Invalid value reported for GL_TESS_GEN_POINT_MODE_EXT property.");
506         }
507 
508         if ((glw::GLuint)gen_vertex_order_value != test.expected_gen_vertex_order_value)
509         {
510             m_testCtx.getLog() << tcu::TestLog::Message
511                                << "Invalid value reported for GL_TESS_GEN_VERTEX_ORDER_EXT property; "
512                                << " expected: " << test.expected_gen_vertex_order_value
513                                << ", retrieved: " << gen_vertex_order_value << tcu::TestLog::EndMessage;
514 
515             TCU_FAIL("Invalid value reported for GL_TESS_GEN_VERTEX_ORDER_EXT property.");
516         }
517     } /* for (all test descriptors) */
518 
519     /* All done */
520     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
521     return STOP;
522 }
523 
524 } /* namespace glcts */
525