1#ifndef _ESEXTCTESSELLATIONSHADERTESSELLATION_HPP
2#define _ESEXTCTESSELLATIONSHADERTESSELLATION_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 "tcuDefs.hpp"
30
31namespace glcts
32{
33/** A DEQP CTS test group that collects all tests that verify tessellation
34 *  functionality for multiple primitive modes at once, as opposed to some
35 *  other tests that are mode-specific.
36 */
37class TessellationShaderTessellationTests : public glcts::TestCaseGroupBase
38{
39public:
40	/* Public methods */
41	TessellationShaderTessellationTests(glcts::Context& context, const ExtParameters& extParams);
42
43	virtual ~TessellationShaderTessellationTests(void)
44	{
45	}
46
47	void init(void);
48
49private:
50	/* Private methods */
51	TessellationShaderTessellationTests(const TessellationShaderTessellationTests& other);
52	TessellationShaderTessellationTests& operator=(const TessellationShaderTessellationTests& other);
53};
54
55/** Implementation of Test Case 24
56 *
57 *  Make sure that patches, for which relevant outer tessellation levels have
58 *  been defined to zero or less, are discarded by the tessellation
59 *  primitive generator. Confirm that such patches never reach tessellation
60 *  evaluation shader program.
61 *  Cover all three tessellation primitive generator modes (triangles, quads,
62 *  isolines).
63 *  Note that an assumption was made here that TE's primitive id counter
64 *  works on output patches that are generated afresh from data fed by TC,
65 *  meaning XFBed TE-stage gl_PrimitiveID should be a sequential set, and
66 *  XFBed TC-stage gl_PrimitiveID should be missing every 4th and 6th patch
67 *  vertices.
68 *  This is backed by http://www.khronos.org/bugzilla/show_bug.cgi?id=754
69 *
70 *  Technical details:
71 *
72 *  0. If (gl_PrimitiveID % 4) == 0, TC should set all relevant outer
73 *     tessellation levels to 0.
74 *  1. If (gl_PrimitiveID % 4) == 2, TC should set all relevant outer
75 *     tessellation level to -1.
76 *  2. If (gl_PrimitiveID % 4) == 1 OR (gl_PrimitiveID % 4) == 3, TC should
77 *     set all relevant outer tessellation levels to 1.
78 *  3. Inner tessellation level should always be set to 1.
79 *  4. TC should also set a per-vertex output variable to gl_PrimitiveID
80 *     value.
81 *  5. TC should also pass gl_PrimitiveID to TE.
82 *  6. TE should store both pieces of data using Transform Feedback for each
83 *     patch vertex processed. Test passes if the data retrieved is valid.
84 *
85 *
86 **/
87class TessellationShaderTessellationInputPatchDiscard : public TestCaseBase
88{
89public:
90	/* Public methods */
91	TessellationShaderTessellationInputPatchDiscard(Context& context, const ExtParameters& extParams);
92
93	virtual ~TessellationShaderTessellationInputPatchDiscard(void)
94	{
95	}
96
97	virtual void		  deinit(void);
98	void				  initTest(void);
99	virtual IterateResult iterate(void);
100
101private:
102	/* Private type definitions */
103	/** Defines a single test pass */
104	typedef struct _run
105	{
106		glw::GLuint					 po_id;
107		_tessellation_primitive_mode primitive_mode;
108		glw::GLuint					 tc_id;
109		glw::GLuint					 te_id;
110
111		_run()
112		{
113			po_id		   = 0;
114			primitive_mode = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
115			tc_id		   = 0;
116			te_id		   = 0;
117		}
118	} _run;
119
120	/** Defines a vector of test passes */
121	typedef std::vector<_run>	 _runs;
122	typedef _runs::const_iterator _runs_const_iterator;
123
124	/* Private methods */
125	std::string getTCCode();
126	std::string getTECode(_tessellation_primitive_mode primitive_mode);
127
128	void deinitRun(_run& test);
129	void initRun(_run& test, _tessellation_primitive_mode primitive_mode);
130
131	/* Private variables */
132	glw::GLuint m_bo_id;
133	glw::GLuint m_fs_id;
134	glw::GLuint m_vs_id;
135	glw::GLuint m_vao_id;
136
137	_runs					 m_runs;
138	TessellationShaderUtils* m_utils_ptr;
139};
140
141/**  Implementation for Test Case 18
142 *
143 *   Make sure that tessellation control shader is fed with correct gl_InvocationID
144 *   values.
145 *   Make sure that tessellation control and tessellation evaluation shaders are
146 *   fed with correct gl_PatchVerticesIn values.
147 *   Make sure that tessellation control and tessellation evaluation shaders are
148 *   fed with correct gl_PrimitiveID values. Make sure restarting a primitive
149 *   topology does not restart primitive counter.
150 *
151 *   Technical details:
152 *
153 *   0. The test to be executed for all three geometry types supported by
154 *      the tessellator. The draw calls used should draw at least a few
155 *      instances of a set of patches generating a few primitives for each type
156 *      considered. Vertex arrayed and indiced draw calls should be tested.
157 *      A few vertices-per-patch configurations should be considered.
158 *
159 *   1. Tessellation control shader to pass gl_InvocationID to tessellation
160 *      evaluation shader for XFB, for later inspection. The values captured
161 *      should run from 0 to the last invocation number for particular draw
162 *      call. Whole range should be covered by exactly one appearance of each index.
163 *
164 *   2. Tessellation control shader should pass gl_PatchVerticesIn value to
165 *      tessellation evaluation shader. The value passed from TC, as well as
166 *      gl_PatchVerticesIn value exposed to TE should be captured for later
167 *      inspection.
168 *
169 *   3. Step 2 should be repeated for gl_PrimitiveID. The test should confirm
170 *      that using a primitive restart index does not reset the counter, when
171 *      indiced draw calls are tested.
172 **/
173class TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID : public TestCaseBase
174{
175public:
176	/* Public methods */
177	TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(Context&			   context,
178																			  const ExtParameters& extParams);
179
180	virtual ~TessellationShaderTessellationgl_InvocationID_PatchVerticesIn_PrimitiveID(void)
181	{
182	}
183
184	virtual void		  deinit(void);
185	void				  initTest(void);
186	virtual IterateResult iterate(void);
187
188private:
189	/* Private type definitions */
190	/** Defines a single test run */
191	typedef struct _run
192	{
193		glw::GLuint					 bo_indices_id;
194		unsigned int				 drawcall_count_multiplier;
195		bool						 drawcall_is_indiced;
196		glw::GLuint					 drawcall_n_instances;
197		glw::GLuint					 n_instances;
198		glw::GLint					 n_patch_vertices;
199		unsigned int				 n_restart_indices;
200		unsigned int				 n_result_vertices;
201		glw::GLuint					 po_id;
202		_tessellation_primitive_mode primitive_mode;
203		glw::GLuint					 tc_id;
204		glw::GLuint					 te_id;
205
206		_run()
207		{
208			bo_indices_id			  = 0;
209			drawcall_count_multiplier = 0;
210			drawcall_is_indiced		  = false;
211			drawcall_n_instances	  = 0;
212			n_result_vertices		  = 0;
213			n_instances				  = 0;
214			n_patch_vertices		  = 0;
215			n_restart_indices		  = 0;
216			po_id					  = 0;
217			primitive_mode			  = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
218			tc_id					  = 0;
219			te_id					  = 0;
220		}
221	} _run;
222
223	/** Defines a vector of test runs */
224	typedef std::vector<_run>	 _runs;
225	typedef _runs::const_iterator _runs_const_iterator;
226
227	/* Private methods */
228	std::string getTCCode(glw::GLuint n_patch_vertices);
229	std::string getTECode(_tessellation_primitive_mode primitive_mode);
230
231	void deinitRun(_run& run);
232
233	void initRun(_run& run, _tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices, bool is_indiced,
234				 glw::GLint n_instances, unsigned int drawcall_count_multiplier);
235
236	/* Private variables */
237	glw::GLuint m_bo_id;
238	glw::GLuint m_fs_id;
239	glw::GLuint m_vs_id;
240	glw::GLuint m_vao_id;
241
242	_runs					 m_runs;
243	TessellationShaderUtils* m_utils_ptr;
244};
245
246/** Implementation of Test Case 51
247 *
248 *  Make sure that coordinates of all triangles generated by fixed-function
249 *  tessellation primitive generator meet the barycentric coordinate requirement
250 *                            u + v + w = 1
251 *
252 *  Consider a few inner/outer tessellation level combinations
253 *  for triangle and quad inputs of a tessellation evaluation shader.
254 *
255 *  Epsilon: 1e-5. This is dictated by the language in ES 3.0 specification,
256 *  which seems to be the best pick, given that the tessellator is
257 *  a fixed-function unit.
258 *
259 *  Make sure that gl_TessCoord is not an array.
260 *  Make sure that gl_TessCoord is not accessible for any of the vertices in
261 *  gl_in[].
262 *  Make sure that (u, v, w) coordinates are in range [0, 1] for all
263 *  tessellation primitive modes.
264 *  Make sure that the w coordinate is always zero for "quads" and "isolines"
265 *  tessellation primitive modes.
266 *
267 *  This test should be executed in two invocations, depending on the test type:
268 *
269 *  * Without a tessellation control shader, where the patch tessellation levels
270 *    are configured by using glPatchParameterfv() function (*);
271 *  * With a tessellation control shader used to configure the levels;
272 *
273 *  (*) Only applies to Desktop
274 *
275 **/
276class TessellationShaderTessellationgl_TessCoord : public TestCaseBase
277{
278	static std::string getTypeName(_tessellation_test_type test_type);
279
280public:
281	/* Public methods */
282	TessellationShaderTessellationgl_TessCoord(Context& context, const ExtParameters& extParams,
283											   _tessellation_test_type test_type);
284
285	virtual ~TessellationShaderTessellationgl_TessCoord(void)
286	{
287	}
288
289	virtual void		  deinit(void);
290	void				  initTest(void);
291	virtual IterateResult iterate(void);
292
293private:
294	/* Private type definitions */
295	/** Defines a single test pass */
296	typedef struct _test_descriptor
297	{
298		glw::GLint							n_patch_vertices;
299		glw::GLuint							po_id;
300		_tessellation_primitive_mode		primitive_mode;
301		glw::GLuint							tc_id;
302		glw::GLuint							te_id;
303		glw::GLfloat						tess_level_inner[2];
304		glw::GLfloat						tess_level_outer[4];
305		_tessellation_test_type				type;
306		_tessellation_shader_vertex_spacing vertex_spacing;
307
308		glw::GLint inner_tess_level_uniform_location;
309		glw::GLint outer_tess_level_uniform_location;
310
311		_test_descriptor()
312		{
313			memset(tess_level_inner, 0, sizeof(tess_level_inner));
314			memset(tess_level_outer, 0, sizeof(tess_level_outer));
315
316			n_patch_vertices = 0;
317			po_id			 = 0;
318			primitive_mode   = TESSELLATION_SHADER_PRIMITIVE_MODE_UNKNOWN;
319			tc_id			 = 0;
320			te_id			 = 0;
321			type			 = TESSELLATION_TEST_TYPE_UNKNOWN;
322			vertex_spacing   = TESSELLATION_SHADER_VERTEX_SPACING_UNKNOWN;
323
324			inner_tess_level_uniform_location = -1;
325			outer_tess_level_uniform_location = -1;
326		}
327	} _test_descriptor;
328
329	/** Defines a vector of test passes */
330	typedef std::vector<_test_descriptor> _tests;
331	typedef _tests::const_iterator		  _tests_const_iterator;
332
333	/* Private methods */
334	std::string getTCCode(glw::GLint n_patch_vertices);
335
336	std::string getTECode(_tessellation_shader_vertex_spacing vertex_spacing,
337						  _tessellation_primitive_mode		  primitive_mode);
338
339	void deinitTestDescriptor(_test_descriptor& test);
340
341	void initTestDescriptor(_test_descriptor& test, _tessellation_shader_vertex_spacing vertex_spacing,
342							_tessellation_primitive_mode primitive_mode, glw::GLint n_patch_vertices,
343							const float* inner_tess_levels, const float* outer_tess_levels,
344							_tessellation_test_type test_type);
345
346	/* Private variables */
347	_tessellation_test_type m_test_type;
348	glw::GLuint				m_bo_id;
349	glw::GLuint				m_broken_ts_id;
350	glw::GLuint				m_fs_id;
351	glw::GLuint				m_vs_id;
352	glw::GLuint				m_vao_id;
353
354	_tests					 m_tests;
355	TessellationShaderUtils* m_utils_ptr;
356};
357
358/* This test class implements the following test cases:
359 *
360 *   20. Make sure it is possible to use up to GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT/4
361 *       vec4 input variables in a tessellation control shader.
362 *       Make sure it is possible to use up to GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT/4
363 *       vec4 input variables in a tessellation evaluation shader.
364 *       This test should issue at least one draw call and verify the results to
365 *       make sure the implementation actually supports the maximums it reports.
366 *
367 *   21. Make sure it is possible to use up to GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT/4
368 *       vec4 per-vertex output variables in a tessellation control shader.
369 *       Make sure it is possible to use up to GL_MAX_TESS_PATCH_COMPONENTS_EXT/4
370 *       vec4 per-patch output variables in a tessellation control shader.
371 *       Make sure it is possible to use up to GL_MAX_TESS_PATCH_COMPONENTS_EXT/4
372 *       vec4 per-patch input variables in a tessellation evaluation shader.
373 *       Make sure it is possible to use up to GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT/4
374 *       vec4 per-vertex output variables in a tessellation evaluation shader.
375 *
376 *       NOTE: The test should separately check if a maximum number of per-vertex and
377 *             per-patch output variables used in a tessellation control shader works
378 *             correctly. This is due to a risk that, had both types been used at once,
379 *             the maximum amount of output components supported for tessellation
380 *             control shader GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT may
381 *             have been exceeded for implementations, for which the property is
382 *             not equal to:
383 *
384 *             (per-vertex output component count multiplied by output patch size +
385 *              + per-patch output component count).
386 *
387 *       This test should issue at least one draw call and verify the results to
388 *       make sure the implementation actually supports the maximums it reports.
389 *
390 *       Category: Functional Test.
391 *       Priority: Must-Have
392 *
393 *  The test is implemented by checking two different cases:
394 *  1) In first case, it makes sure it is possible to use up to:
395 *     - GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT     / 4 vec4 per-vertex variables in tessellation control shader,
396 *     - GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT    / 4 vec4 per-vertex variables in tessellation control shader,
397 *     - GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT  / 4 vec4 per-vertex variables in tessellation evaluation shader,
398 *     - GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT / 4 vec4 per-vertex variables in tessellation evaluation shader.
399 *
400 *  2) In second case, it makes sure it is possible to use up to:
401 *     - GL_MAX_TESS_PATCH_COMPONENTS_EXT/4 vec4 per-patch variables in tessellation control shader,
402 *     - GL_MAX_TESS_PATCH_COMPONENTS_EXT/4 vec4 per-patch variables in tessellation evaluation shader.
403 */
404class TessellationShaderTessellationMaxInOut : public TestCaseBase
405{
406public:
407	/* Public methods */
408	TessellationShaderTessellationMaxInOut(Context& context, const ExtParameters& extParams);
409
410	virtual ~TessellationShaderTessellationMaxInOut()
411	{
412	}
413
414	virtual void		  deinit(void);
415	virtual IterateResult iterate(void);
416
417private:
418	/* private methods */
419	void initBufferObjects(void);
420	void initProgramObjects(void);
421	void initReferenceValues(void);
422	void initTest(void);
423	void retrieveGLConstantValues(void);
424
425	bool compareValues(char const* description, glw::GLfloat* reference_values, int n_reference_values);
426
427	/* private variables */
428	glw::GLuint m_po_id_1; /* program object name for case 1 */
429	glw::GLuint m_po_id_2; /* program object name for case 2 */
430
431	glw::GLuint m_fs_id;	/* fragment shader object name */
432	glw::GLuint m_tcs_id_1; /* tessellation control shader object name for case 1 */
433	glw::GLuint m_tcs_id_2; /* tessellation control shader object name for case 2 */
434	glw::GLuint m_tes_id_1; /* tessellation evaluation shader object name for case 1 */
435	glw::GLuint m_tes_id_2; /* tessellation evaluation shader object name for case 2 */
436	glw::GLuint m_vs_id_1;  /* vertex shader object name for case 1 */
437	glw::GLuint m_vs_id_2;  /* vertex shader object name for case 2 */
438
439	glw::GLuint m_tf_bo_id_1;		/* buffer object name */
440	glw::GLuint m_tf_bo_id_2;		/* buffer object name */
441	glw::GLuint m_patch_data_bo_id; /* buffer object name for patch submission */
442
443	glw::GLuint m_vao_id; /* vertex array object */
444
445	glw::GLint m_gl_max_tess_control_input_components_value;	 /* value of MAX_TESS_CONTROL_INPUT_COMPONENTS */
446	glw::GLint m_gl_max_tess_control_output_components_value;	/* value of MAX_TESS_CONTROL_OUTPUT_COMPONENTS */
447	glw::GLint m_gl_max_tess_evaluation_input_components_value;  /* value of MAX_TESS_EVALUATION_INPUT_COMPONENTS */
448	glw::GLint m_gl_max_tess_evaluation_output_components_value; /* value of MAX_TESS_EVALUATION_OUTPUT_COMPONENTS */
449	glw::GLint
450			   m_gl_max_transform_feedback_interleaved_components_value; /* value of MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS */
451	glw::GLint m_gl_max_tess_patch_components_value;					 /* value of MAX_TESS_PATCH_COMPONENTS */
452	glw::GLint m_gl_max_vertex_output_components_value;					 /* value of MAX_VERTEX_OUTPUT_COMPONENTS */
453
454	glw::GLfloat  m_ref_patch_attributes[4]; /* reference values for max per-patch attributes case 2 */
455	glw::GLfloat* m_ref_vertex_attributes;   /* reference values for max per-vertex attributes case 1 */
456
457	static const char* m_fs_code;	/* fragment shader code */
458	static const char* m_vs_code;	/* vertex shader code */
459	static const char* m_tcs_code_1; /* tessellation control shader code for per vertex components check */
460	static const char* m_tcs_code_2; /* tessellation control shader code per patch components check */
461	static const char* m_tes_code_1; /* tessellation evaluation shader code per vertex components check */
462	static const char* m_tes_code_2; /* tessellation evaluation shader code per patch components check */
463
464	char** m_tf_varyings_names; /* transform feedback varyings names array */
465};
466
467} // namespace glcts
468
469#endif // _ESEXTCTESSELLATIONSHADERTESSELLATION_HPP
470