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