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