1 #ifndef _ESEXTCTESSELLATIONSHADERINVARIANCE_HPP
2 #define _ESEXTCTESSELLATIONSHADERINVARIANCE_HPP
3 /*-------------------------------------------------------------------------
4  * OpenGL Conformance Test Suite
5  * -----------------------------
6  *
7  * Copyright (c) 2014-2016 The Khronos Group Inc.
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  */ /*!
22  * \file
23  * \brief
24  */ /*-------------------------------------------------------------------*/
25 
26 #include "../esextcTestCaseBase.hpp"
27 #include "esextcTessellationShaderUtils.hpp"
28 #include "gluShaderUtil.hpp"
29 #include "glwEnums.hpp"
30 #include "tcuDefs.hpp"
31 
32 namespace glcts
33 {
34 
35 /** A DEQP CTS test group that collects all tests that verify invariance
36  *  conformance.
37  */
38 class TessellationShaderInvarianceTests : public glcts::TestCaseGroupBase
39 {
40 public:
41 	/* Public methods */
42 	TessellationShaderInvarianceTests(glcts::Context& context, const ExtParameters& extParams);
43 
~TessellationShaderInvarianceTests(void)44 	virtual ~TessellationShaderInvarianceTests(void)
45 	{
46 	}
47 
48 	virtual void init(void);
49 
50 private:
51 	/* Private methods */
52 	TessellationShaderInvarianceTests(const TessellationShaderInvarianceTests& other);
53 	TessellationShaderInvarianceTests& operator=(const TessellationShaderInvarianceTests& other);
54 };
55 
56 /** Base class that provides shared invariance test implementation. Invariance
57  *  rule test need only to implement the abstract methods.
58  **/
59 class TessellationShaderInvarianceBaseTest : public TestCaseBase
60 {
61 public:
62 	/* Public methods */
63 	TessellationShaderInvarianceBaseTest(Context& context, const ExtParameters& extParams, const char* name,
64 										 const char* description);
65 
~TessellationShaderInvarianceBaseTest(void)66 	virtual ~TessellationShaderInvarianceBaseTest(void)
67 	{
68 	}
69 
70 	virtual void		  deinit(void);
71 	virtual IterateResult iterate(void);
72 
73 protected:
74 	/* Protected variables */
75 	TessellationShaderUtils* m_utils_ptr;
76 
77 	virtual void executeDrawCall(unsigned int n_iteration);
78 	virtual unsigned int getAmountOfIterations() = 0;
79 	virtual unsigned int getDrawCallCountArgument();
80 	virtual std::string getFSCode(unsigned int n_iteration);
81 	virtual const char* getInnerTessLevelUniformName();
82 	virtual const char* getOuterTessLevelUniformName();
83 
84 	virtual void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels,
85 										float* out_outer_tess_levels, bool* out_point_mode,
86 										_tessellation_primitive_mode*		  out_primitive_mode,
87 										_tessellation_shader_vertex_ordering* out_vertex_ordering,
88 										unsigned int*						  out_result_buffer_size) = 0;
89 
90 	virtual std::string getTCCode(unsigned int n_iteration);
91 	virtual std::string getTECode(unsigned int n_iteration) = 0;
92 	virtual std::string getVSCode(unsigned int n_iteration);
93 
94 	virtual void getXFBProperties(unsigned int n_iteration, unsigned int* out_n_names, const char*** out_names);
95 
96 	virtual void verifyResultDataForIteration(unsigned int n_iteration, const void* data);
97 
98 	virtual void verifyResultData(const void** all_iterations_data);
99 
100 private:
101 	/* Private type definitions */
102 
103 	/* Private methods */
104 	void initTest();
105 
106 	/* Private variables */
107 	typedef struct _test_program
108 	{
109 		glw::GLuint po_id;
110 
111 		glw::GLuint inner_tess_level_uniform_location;
112 		glw::GLuint outer_tess_level_uniform_location;
113 
114 	} _test_program;
115 
116 	/* Defines a vector of program objects. Index corresponds to iteration index */
117 	typedef std::vector<_test_program> _programs;
118 	typedef _programs::const_iterator  _programs_const_iterator;
119 	typedef _programs::iterator		   _programs_iterator;
120 
121 	glw::GLuint m_bo_id;
122 	_programs   m_programs;
123 	glw::GLuint m_qo_tfpw_id;
124 	glw::GLuint m_vao_id;
125 };
126 
127 /** Implementation of Test Case 42
128  *
129  *  Make sure that invariance rule 1 is adhered to. Using a program object
130  *  consisting of a fragment/tessellation control/tessellation evaluation/
131  *  vertex shaders, render three points/lines/triangles (A, B, C) and
132  *  store vertices output by the tessellation evaluation shader.  Then render
133  *  the geometry in (B, C, A) order, using the same program object. Test
134  *  passes if vertices stored in two different iterations for the same
135  *  triangle are identical. Owing to rule 8, assume zero epsilon.
136  **/
137 class TessellationShaderInvarianceRule1Test : public TessellationShaderInvarianceBaseTest
138 {
139 public:
140 	/* Public methods */
141 	TessellationShaderInvarianceRule1Test(Context& context, const ExtParameters& extParams);
142 	virtual ~TessellationShaderInvarianceRule1Test();
143 
144 protected:
145 	/* Protected methods */
146 	unsigned int getAmountOfIterations();
147 	unsigned int getDrawCallCountArgument();
148 
149 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
150 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
151 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
152 								unsigned int*						  out_result_buffer_size);
153 
154 	std::string getTECode(unsigned int n_iteration);
155 	void verifyResultData(const void** all_iterations_data);
156 };
157 
158 /** Implementation of Test Case 43
159  *
160  *  Make sure that invariance rule 2 is adhered to. Using a program object
161  *  consisting of a fragment/tessellation control/tessellation evaluation/
162  *  vertex shaders, render a number of full-screen triangles/quads, each
163  *  instance rendered with different inner tessellation level but identical
164  *  outer tessellation level and spacing input layout qualifiers. Test passes
165  *  if outer edge's vertices are the same for both types of geometry
166  *  (each type considered separately).
167  **/
168 class TessellationShaderInvarianceRule2Test : public TessellationShaderInvarianceBaseTest
169 {
170 public:
171 	/* Public methods */
172 	TessellationShaderInvarianceRule2Test(Context& context, const ExtParameters& extParams);
173 	virtual ~TessellationShaderInvarianceRule2Test();
174 
175 protected:
176 	/* Protected methods */
177 	unsigned int getAmountOfIterations();
178 
179 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
180 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
181 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
182 								unsigned int*						  out_result_buffer_size);
183 
184 	std::string getTECode(unsigned int n_iteration);
185 	void verifyResultData(const void** all_iterations_data);
186 
187 private:
188 	/* Private variables */
189 	unsigned int m_n_tessellated_vertices[4 /* iterations in total */];
190 };
191 
192 /** Implementation of Test Case 44
193  *
194  *  Make sure that invariance rule 3 is adhered to. Using a program object
195  *  consisting of a fragment/tessellation control/tessellation evaluation/
196  *  vertex shaders, tessellate a number of triangles/quads/isolines geometry
197  *  with different inner/outer/vertex spacing input layout qualifiers.
198  *  Capture vertices generated by tessellation evaluation stage and make sure
199  *  that generated vertices are symmetrical. Owing to rule 8, assume zero
200  *  epsilon.
201  **/
202 class TessellationShaderInvarianceRule3Test : public TessellationShaderInvarianceBaseTest
203 {
204 public:
205 	/* Public methods */
206 	TessellationShaderInvarianceRule3Test(Context& context, const ExtParameters& extParams);
207 	virtual ~TessellationShaderInvarianceRule3Test();
208 
209 protected:
210 	/* Protected methods */
211 	unsigned int getAmountOfIterations();
212 
213 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
214 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
215 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
216 								unsigned int*						  out_result_buffer_size);
217 
218 	std::string getTECode(unsigned int n_iteration);
219 
220 	void verifyResultDataForIteration(unsigned int n_iteration, const void* data);
221 
222 private:
223 	/* Private type definitions */
224 	typedef struct _test_iteration
225 	{
226 		glw::GLfloat						inner_tess_levels[2];
227 		glw::GLfloat						outer_tess_levels[4];
228 		_tessellation_primitive_mode		primitive_mode;
229 		_tessellation_shader_vertex_spacing vertex_spacing;
230 
231 		unsigned int n_vertices;
232 
_test_iterationglcts::TessellationShaderInvarianceRule3Test::_test_iteration233 		_test_iteration()
234 		{
235 			memset(inner_tess_levels, 0, sizeof(inner_tess_levels));
236 			memset(outer_tess_levels, 0, sizeof(outer_tess_levels));
237 
238 			primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
239 			vertex_spacing = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
240 
241 			n_vertices = 0;
242 		}
243 	} _test_iteration;
244 
245 	typedef std::vector<_test_iteration>	 _test_iterations;
246 	typedef _test_iterations::const_iterator _test_iterations_const_iterator;
247 
248 	/* Private methods */
249 	void deinitTestIterations();
250 	void initTestIterations();
251 
252 	/* Private fields */
253 	_test_iterations m_test_iterations;
254 };
255 
256 /** Implementation of Test Case 45
257  *
258  *  Make sure that invariance rule 4 is adhered to. Using a program object
259  *  consisting of a fragment/tessellation control/tessellation evaluation/
260  *  vertex shaders, tessellate a number of triangular and quad geometry with
261  *  different inner tessellation level input layout qualifiers.
262  *  Capture vertices generated by tessellation evaluation stage and make sure
263  *  that all sets of vertices generated when subdividing outer edges are
264  *  independent of the specific edge subdivided.
265  *
266  *  Technical details:
267  *
268  *  1. The test should use a number of different inner+outer
269  *     tessellation levels+vertex spacing mode configuration
270  *     combinations, each resulting in a different vertex set for
271  *     the generator primitive type considered.
272  *     In first iteration, it should draw a screen quad, and
273  *     in the other a triangle should be rendered.
274  *  2. The test should capture vertices output in TE stage. The
275  *     rasterizer discard mode can be enabled, as the test is not
276  *     expected to analyse visual output.
277  *  3. For quad tessellation, the test should identify vertices
278  *     generated for top outer edge and make sure that remaining
279  *     outer edges of the quad are built of vertices that conform
280  *     to the rule.
281  *  4. For triangular tessellation, the test should identify vertices
282  *     generated for one of the outer edges and then check if the other
283  *     two outer edges have been generated in conformance to the rule.
284  **/
285 class TessellationShaderInvarianceRule4Test : public TessellationShaderInvarianceBaseTest
286 {
287 public:
288 	/* Public methods */
289 	TessellationShaderInvarianceRule4Test(Context& context, const ExtParameters& extParams);
290 	virtual ~TessellationShaderInvarianceRule4Test();
291 
292 protected:
293 	/* Protected methods */
294 	unsigned int getAmountOfIterations();
295 
296 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
297 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
298 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
299 								unsigned int*						  out_result_buffer_size);
300 
301 	std::string getTECode(unsigned int n_iteration);
302 
303 	void verifyResultDataForIteration(unsigned int n_iteration, const void* data);
304 
305 private:
306 	/* Private type definitions */
307 	typedef struct _test_iteration
308 	{
309 		glw::GLfloat						inner_tess_levels[2];
310 		glw::GLfloat						outer_tess_levels[4];
311 		_tessellation_primitive_mode		primitive_mode;
312 		_tessellation_shader_vertex_spacing vertex_spacing;
313 
314 		unsigned int n_vertices;
315 
_test_iterationglcts::TessellationShaderInvarianceRule4Test::_test_iteration316 		_test_iteration()
317 		{
318 			memset(inner_tess_levels, 0, sizeof(inner_tess_levels));
319 			memset(outer_tess_levels, 0, sizeof(outer_tess_levels));
320 
321 			primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
322 			vertex_spacing = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
323 
324 			n_vertices = 0;
325 		}
326 	} _test_iteration;
327 
328 	typedef std::vector<_test_iteration>	 _test_iterations;
329 	typedef _test_iterations::const_iterator _test_iterations_const_iterator;
330 
331 	/* Private methods */
332 	void deinitTestIterations();
333 	void initTestIterations();
334 
335 	bool isVertexDefined(const float* vertex_data, unsigned int n_vertices, const float* vertex_data_seeked,
336 						 unsigned int n_vertex_data_seeked_components);
337 
338 	/* Private fields */
339 	_test_iterations m_test_iterations;
340 };
341 
342 /** Implementation of Test Case 46
343  *
344  *  Make sure that Rule 5 is adhered to. Using a program object
345  *  consisting of a fragment/tessellation control/tessellation evaluation/
346  *  vertex shaders, tessellate a number of triangles/quads/isolines
347  *  geometry with different vertex ordering input layout qualifiers. Capture
348  *  vertices generated by tessellation evaluation stage and make sure that each
349  *  iteration defines exactly the same set of vertices, although in different
350  *  order.
351  *
352  **/
353 class TessellationShaderInvarianceRule5Test : public TessellationShaderInvarianceBaseTest
354 {
355 public:
356 	/* Public methods */
357 	TessellationShaderInvarianceRule5Test(Context& context, const ExtParameters& extParams);
358 	virtual ~TessellationShaderInvarianceRule5Test();
359 
360 protected:
361 	/* Protected methods */
362 	unsigned int getAmountOfIterations();
363 
364 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
365 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
366 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
367 								unsigned int*						  out_result_buffer_size);
368 
369 	std::string getTECode(unsigned int n_iteration);
370 	void verifyResultData(const void** all_iterations_data);
371 
372 private:
373 	/* Private type definitions */
374 	typedef struct _test_iteration
375 	{
376 		glw::GLfloat						 inner_tess_levels[2];
377 		glw::GLfloat						 outer_tess_levels[4];
378 		_tessellation_primitive_mode		 primitive_mode;
379 		_tessellation_shader_vertex_ordering vertex_ordering;
380 
381 		unsigned int n_vertices;
382 
_test_iterationglcts::TessellationShaderInvarianceRule5Test::_test_iteration383 		_test_iteration()
384 		{
385 			memset(inner_tess_levels, 0, sizeof(inner_tess_levels));
386 			memset(outer_tess_levels, 0, sizeof(outer_tess_levels));
387 
388 			primitive_mode  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
389 			vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN;
390 
391 			n_vertices = 0;
392 		}
393 	} _test_iteration;
394 
395 	typedef std::vector<_test_iteration>	 _test_iterations;
396 	typedef _test_iterations::const_iterator _test_iterations_const_iterator;
397 
398 	/* Private methods */
399 	void			 deinitTestIterations();
400 	_test_iteration& getTestForIteration(unsigned int n_iteration);
401 	void initTestIterations();
402 	bool isVertexDefined(const float* vertex_data, unsigned int n_vertices, const float* vertex_data_seeked,
403 						 unsigned int n_vertex_data_seeked_components);
404 
405 	/* Private fields */
406 	_test_iterations m_test_triangles_iterations;
407 	_test_iterations m_test_quads_iterations;
408 };
409 
410 /**  Implementation of Test Case 47
411  *
412  *   Make sure that invariance rule 6 is adhered to. Using a program object
413  *   consisting of a fragment/tessellation control/tessellation evaluation/
414  *   vertex shaders, tessellate a number of triangles/quads geometry
415  *   with different inner tessellation levels/vertex spacing input layout qualifiers.
416  *   Capture vertices generated by tessellation evaluation stage and make sure
417  *   that all interior triangles generated during tessellation are identical
418  *   except for vertex and triangle order.
419  **/
420 class TessellationShaderInvarianceRule6Test : public TessellationShaderInvarianceBaseTest
421 {
422 public:
423 	/* Public methods */
424 	TessellationShaderInvarianceRule6Test(Context& context, const ExtParameters& extParams);
425 	virtual ~TessellationShaderInvarianceRule6Test();
426 
427 protected:
428 	/* Protected methods */
429 	unsigned int getAmountOfIterations();
430 
431 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
432 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
433 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
434 								unsigned int*						  out_result_buffer_size);
435 
436 	std::string getTECode(unsigned int n_iteration);
437 	void verifyResultData(const void** all_iterations_data);
438 
439 private:
440 	/* Private type definitions */
441 	typedef struct _test_iteration
442 	{
443 		glw::GLfloat						 inner_tess_levels[2];
444 		glw::GLfloat						 outer_tess_levels[4];
445 		_tessellation_primitive_mode		 primitive_mode;
446 		_tessellation_shader_vertex_ordering vertex_ordering;
447 
448 		unsigned int n_vertices;
449 
_test_iterationglcts::TessellationShaderInvarianceRule6Test::_test_iteration450 		_test_iteration()
451 		{
452 			memset(inner_tess_levels, 0, sizeof(inner_tess_levels));
453 			memset(outer_tess_levels, 0, sizeof(outer_tess_levels));
454 
455 			primitive_mode  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
456 			vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN;
457 
458 			n_vertices = 0;
459 		}
460 	} _test_iteration;
461 
462 	typedef std::vector<_test_iteration>	 _test_iterations;
463 	typedef _test_iterations::const_iterator _test_iterations_const_iterator;
464 
465 	/* Private methods */
466 	void			 deinitTestIterations();
467 	_test_iteration& getTestForIteration(unsigned int n_iteration);
468 	void initTestIterations();
469 
470 	/* Private fields */
471 	_test_iterations m_test_triangles_iterations;
472 	_test_iterations m_test_quads_iterations;
473 };
474 
475 /**  Implementation of Test Case 48
476  *
477  *   Make sure that invariance rule 7 is adhered to. Using a program object
478  *   consisting of a fragment/tessellation control/tessellation evaluation/
479  *   vertex shaders, tessellate a number of triangles/quads geometry
480  *   with different vertex spacing input layout qualifiers. For each such
481  *   case, the test should verify that modification of a single outer tessellation
482  *   level only affects tessellation coordinates generated for a corresponding
483  *   edge. Verification should be carried out by capturing vertices generated for
484  *   tessellation evaluation stage and making sure that each iteration defines
485  *   exactly the same set of triangles connecting inner and outer edge of the
486  *   tessellated geometry for all but the modified edge.
487  **/
488 class TessellationShaderInvarianceRule7Test : public TessellationShaderInvarianceBaseTest
489 {
490 public:
491 	/* Public methods */
492 	TessellationShaderInvarianceRule7Test(Context& context, const ExtParameters& extParams);
493 	virtual ~TessellationShaderInvarianceRule7Test();
494 
495 protected:
496 	/* Protected methods */
497 	unsigned int getAmountOfIterations();
498 
499 	void getIterationProperties(unsigned int n_iteration, float* out_inner_tess_levels, float* out_outer_tess_levels,
500 								bool* out_point_mode, _tessellation_primitive_mode* out_primitive_mode,
501 								_tessellation_shader_vertex_ordering* out_vertex_ordering,
502 								unsigned int*						  out_result_buffer_size);
503 
504 	std::string getTECode(unsigned int n_iteration);
505 	void verifyResultData(const void** all_iterations_data);
506 
507 private:
508 	/* Private type definitions */
509 	typedef struct _test_iteration
510 	{
511 		glw::GLfloat						 inner_tess_levels[2];
512 		glw::GLfloat						 outer_tess_levels[4];
513 		_tessellation_primitive_mode		 primitive_mode;
514 		_tessellation_shader_vertex_ordering vertex_ordering;
515 
516 		bool		 is_base_iteration;
517 		unsigned int n_modified_outer_tess_level;
518 		unsigned int n_vertices;
519 
_test_iterationglcts::TessellationShaderInvarianceRule7Test::_test_iteration520 		_test_iteration()
521 		{
522 			memset(inner_tess_levels, 0, sizeof(inner_tess_levels));
523 			memset(outer_tess_levels, 0, sizeof(outer_tess_levels));
524 
525 			primitive_mode  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
526 			vertex_ordering = TESSELLATION_SHADER_VERTEX_ORDERING_UNKNOWN;
527 
528 			is_base_iteration			= false;
529 			n_modified_outer_tess_level = 0;
530 			n_vertices					= 0;
531 		}
532 	} _test_iteration;
533 
534 	typedef std::vector<_test_iteration>	 _test_iterations;
535 	typedef _test_iterations::const_iterator _test_iterations_const_iterator;
536 
537 	/* Private methods */
538 	void deinitTestIterations();
539 
540 	unsigned int getTestIterationIndex(bool is_triangles_iteration, const float* inner_tess_levels,
541 									   const float*							outer_tess_levels,
542 									   _tessellation_shader_vertex_ordering vertex_ordering,
543 									   unsigned int							n_modified_outer_tess_level);
544 
545 	_test_iteration& getTestForIteration(unsigned int n_iteration);
546 	void initTestIterations();
547 
548 	bool isTriangleDefinedInVertexDataSet(const float* base_triangle_data, const float* vertex_data,
549 										  unsigned int vertex_data_n_vertices);
550 
551 	bool isVertexDefined(const float* vertex_data, unsigned int n_vertices, const float* vertex_data_seeked,
552 						 unsigned int n_vertex_data_seeked_components);
553 
554 	/* Private fields */
555 	_test_iterations m_test_triangles_iterations;
556 	_test_iterations m_test_quads_iterations;
557 };
558 
559 } // namespace glcts
560 
561 #endif // _ESEXTCTESSELLATIONSHADERINVARIANCE_HPP
562