• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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