1#ifndef _ESEXTCGEOMETRYSHADERRENDERING_HPP
2#define _ESEXTCGEOMETRYSHADERRENDERING_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
28namespace glcts
29{
30
31/** Supported geometry shader output layout qualifiers */
32typedef enum {
33	/* points */
34	SHADER_OUTPUT_TYPE_POINTS,
35	/* lines */
36	SHADER_OUTPUT_TYPE_LINE_STRIP,
37	/* triangles */
38	SHADER_OUTPUT_TYPE_TRIANGLE_STRIP,
39
40	/* Always last */
41	SHADER_OUTPUT_TYPE_COUNT
42} _shader_output_type;
43
44/** Implements Geometry Shader conformance test group 1.
45 *
46 *  Note that actual testing is handled by classes implementing GeometryShaderRenderingCase
47 *  interface. This class implements DEQP CTS test case interface, meaning it is only
48 *  responsible for executing the test and reporting the results back to CTS.
49 *
50 **/
51class GeometryShaderRendering : public TestCaseGroupBase
52{
53public:
54	/* Public methods */
55	GeometryShaderRendering(Context& context, const ExtParameters& extParams, const char* name,
56							const char* description);
57
58	virtual ~GeometryShaderRendering()
59	{
60	}
61
62	virtual void init(void);
63
64private:
65	/* Private type definitions */
66	typedef enum {
67		/* points */
68		SHADER_INPUT_POINTS,
69
70		/* lines */
71		SHADER_INPUT_LINES,
72
73		/* lines_with_adjacency */
74		SHADER_INPUT_LINES_WITH_ADJACENCY,
75
76		/* triangles */
77		SHADER_INPUT_TRIANGLES,
78
79		/* triangles_with_adjacency */
80		SHADER_INPUT_TRIANGLES_WITH_ADJACENCY,
81
82		/* Always last */
83		SHADER_INPUT_UNKNOWN
84	} _shader_input;
85
86	/* Private methods */
87	const char* getTestName(_shader_input input, _shader_output_type output_type, glw::GLenum drawcall_mode);
88};
89
90/* Defines an interface that all test case classes must implement.
91 *
92 * Base implementation initializes GLES objects later used in the specific test
93 * and fills them with content, as reported by actual test case implementations.
94 *
95 * Instances matching this interface are used by GeometryShaderRendering class
96 * to execute a set of all the tests as defined in the test specification.
97 */
98class GeometryShaderRenderingCase : public TestCaseBase
99{
100public:
101	/* Public type definitions */
102	/** Supported draw call types. */
103	typedef enum {
104		/* glDrawArrays() */
105		DRAW_CALL_TYPE_GL_DRAW_ARRAYS,
106
107		/* glDrawArraysInstanced() */
108		DRAW_CALL_TYPE_GL_DRAW_ARRAYS_INSTANCED,
109
110		/* glDrawElements() */
111		DRAW_CALL_TYPE_GL_DRAW_ELEMENTS,
112
113		/* glDrawElementsInstanced() */
114		DRAW_CALL_TYPE_GL_DRAW_ELEMENTS_INSTANCED,
115
116		/* glDrawRangeElements() */
117		DRAW_CALL_TYPE_GL_DRAW_RANGE_ELEMENTS
118
119	} _draw_call_type;
120
121	/* Public methods */
122	GeometryShaderRenderingCase(Context& Context, const ExtParameters& extParams, const char* name,
123								const char* description);
124
125	virtual ~GeometryShaderRenderingCase()
126	{
127	}
128
129	virtual void deinit();
130	void executeTest(_draw_call_type type);
131	virtual IterateResult iterate();
132
133protected:
134	/* Protected methods */
135	void				 initTest();
136	virtual unsigned int getAmountOfDrawInstances()				   = 0;
137	virtual unsigned int getAmountOfElementsPerInstance()		   = 0;
138	virtual unsigned int getAmountOfVerticesPerInstance()		   = 0;
139	virtual glw::GLenum  getDrawCallMode()						   = 0;
140	virtual std::string  getFragmentShaderCode()				   = 0;
141	virtual std::string  getGeometryShaderCode()				   = 0;
142	virtual glw::GLuint getRawArraysDataBufferSize(bool instanced) = 0;
143	virtual const void* getRawArraysDataBuffer(bool instanced)	 = 0;
144	virtual void getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, unsigned int* out_height) = 0;
145	virtual glw::GLuint getUnorderedArraysDataBufferSize(bool instanced)   = 0;
146	virtual const void* getUnorderedArraysDataBuffer(bool instanced)	   = 0;
147	virtual glw::GLuint getUnorderedElementsDataBufferSize(bool instanced) = 0;
148	virtual const void* getUnorderedElementsDataBuffer(bool instanced)	 = 0;
149	virtual glw::GLenum  getUnorderedElementsDataType()					   = 0;
150	virtual glw::GLubyte getUnorderedElementsMaxIndex()					   = 0;
151	virtual glw::GLubyte getUnorderedElementsMinIndex()					   = 0;
152	virtual std::string  getVertexShaderCode()							   = 0;
153	virtual void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char* data) = 0;
154
155	virtual void setUniformsBeforeDrawCall(_draw_call_type /*drawcall_type*/)
156	{
157	}
158
159	/* Protected variables */
160	deqp::Context& m_context;
161	glw::GLuint	m_instanced_raw_arrays_bo_id;
162	glw::GLuint	m_instanced_unordered_arrays_bo_id;
163	glw::GLuint	m_instanced_unordered_elements_bo_id;
164	glw::GLuint	m_noninstanced_raw_arrays_bo_id;
165	glw::GLuint	m_noninstanced_unordered_arrays_bo_id;
166	glw::GLuint	m_noninstanced_unordered_elements_bo_id;
167	glw::GLuint	m_fs_id;
168	glw::GLuint	m_gs_id;
169	glw::GLuint	m_po_id;
170	glw::GLuint	m_renderingTargetSize_uniform_location;
171	glw::GLuint	m_singleRenderingTargetSize_uniform_location;
172	glw::GLuint	m_vao_id;
173	glw::GLuint	m_vs_id;
174
175	glw::GLuint m_fbo_id;
176	glw::GLuint m_read_fbo_id;
177	glw::GLuint m_to_id;
178
179	glw::GLuint m_instanced_fbo_id;
180	glw::GLuint m_instanced_read_fbo_id;
181	glw::GLuint m_instanced_to_id;
182};
183
184/** Implements Geometry Shader conformance test group 1, 'points' input primitive type case.
185 *  Test specification for this case follows:
186 *
187 *  All sub-tests assume point size & line width of 1 pixel, which is the
188 *  minimum maximum value for both properties in GLES 3.0.
189 *
190 *  Let (R, G, B, A) be the color of the  input point that is to be amplified.
191 *  Color buffer should be cleared with (0, 0, 0, 0) prior to executing each
192 *  of the scenarios.
193 *
194 *  1.1. If "points" output primitive type is used:
195 *
196 *  The geometry shader should emit 9 points in total for a single input.
197 *  Each point should be assigned  a size of 1. The points should be
198 *  positioned, so that they tightly surround the "input" point from left /
199 *  right / top / left sides, as well as from top-left / top-right /
200 *  bottom-left / bottom-right corners but do *not* overlap in screen-space.
201 *
202 *  Additional points should also use (R, G, B, A) color.
203 *
204 *  The test should draw 8 points (one after another, assume a horizontal
205 *  delta of 2 pixels) of varying colors to a 2D texture of resolution 38x3.
206 *  Test succeeds if centers of all emitted points have colors different than
207 *  the background color.
208 *
209 *  1.2. If "lines" output primitive type is used:
210 *
211 *  The geometry shader should draw outlines (built of line segments) of
212 *  three quads nested within each other, as depicted below:
213 *
214 *                           1 1 1 1 1 1 1
215 *                           1 2 2 2 2 2 1
216 *                           1 2 3 3 3 2 1
217 *                           1 2 3 * 3 2 1
218 *                           1 2 3 3 3 2 1
219 *                           1 2 2 2 2 2 1
220 *                           1 1 1 1 1 1 1
221 *
222 *  where each number corresponds to index of the quad and * indicates
223 *  position of the input point which is not drawn.
224 *
225 *  Each quad should be drawn with (R, G, B, A) color.
226 *  The test should draw 8 points (one after another) of varying colors to
227 *  a 2D texture of resolution 54x7. Test succeeds if all pixels making up
228 *  the central quad 2 have valid colors.
229 *
230 *  1.3. If "triangles" output primitive type is used:
231 *
232 *  The geometry shader should generate 2 triangle primitives for a single
233 *  input point:
234 *
235 *  * A) (Bottom-left corner, top-left corner, bottom-right corner), use
236 *       (R, 0, 0, 0) color;
237 *  * B) (Bottom-right corner, top-left corner, top-right corner), use
238 *       (0, G, 0, 0) color;
239 *
240 *  The test should draw 8 points (one after another) of varying colors to
241 *  a 2D texture of resolution of resolution 48x6. Test succeeds if centers
242 *  of the rendered triangles have valid colors.
243 *
244 **/
245class GeometryShaderRenderingPointsCase : public GeometryShaderRenderingCase
246{
247public:
248	/* Public methods */
249	GeometryShaderRenderingPointsCase(Context& context, const ExtParameters& extParams, const char* name,
250									  glw::GLenum drawcall_mode, _shader_output_type output_type);
251
252	virtual ~GeometryShaderRenderingPointsCase();
253
254protected:
255	/* GeometryShaderRenderingCase interface implementation */
256	unsigned int getAmountOfDrawInstances();
257	unsigned int getAmountOfElementsPerInstance();
258	unsigned int getAmountOfVerticesPerInstance();
259	glw::GLenum  getDrawCallMode();
260	std::string  getFragmentShaderCode();
261	std::string  getGeometryShaderCode();
262	glw::GLuint getRawArraysDataBufferSize(bool instanced);
263	const void* getRawArraysDataBuffer(bool instanced);
264	void getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, unsigned int* out_height);
265	glw::GLuint getUnorderedArraysDataBufferSize(bool instanced);
266	const void* getUnorderedArraysDataBuffer(bool instanced);
267	glw::GLuint getUnorderedElementsDataBufferSize(bool instanced);
268	const void* getUnorderedElementsDataBuffer(bool instanced);
269	glw::GLenum  getUnorderedElementsDataType();
270	glw::GLubyte getUnorderedElementsMaxIndex();
271	glw::GLubyte getUnorderedElementsMinIndex();
272	std::string  getVertexShaderCode();
273	void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char* data);
274
275private:
276	/* Private variables */
277	_shader_output_type m_output_type;
278
279	float*		   m_raw_array_data;
280	float*		   m_unordered_array_data;
281	unsigned char* m_unordered_elements_data;
282};
283
284/** Implements Geometry Shader conformance test group 1, 'lines' and
285 *  'lines_adjacency' input primitive type cases.
286 *
287 *  Test specification for this case follows:
288 *
289 *  Assume a point size of 1 pixel and line width of 1 pixel, where
290 *  appropriate.
291 *  Let (R, G, B, A) be the color of start point of the input line and
292 *  (R', G', B', A') be the color of end point of the input line.
293 *
294 *  2.1. If "points" output primitive type is used:
295 *
296 *  The geometry shader should generate 8 points for a single input line segment,
297 *  where each point consists of 9 sub-points tightly forming a quad (with
298 *  the actual point located in the center) in order to emulate larger point
299 *  size. The points should be uniformly distributed over the primitive
300 *  (first point positioned at the start point and the last one located at
301 *  the end point) and their color should linearly interpolate from the
302 *  (R, G, B, A) to (R', G', B', A'). All sub-points should use the same
303 *  color as the parent point.
304 *
305 *  The test should draw the points over a square outline. Each instance should
306 *  draw a set of points occupying a separate outline. Each rectangle should
307 *  occupy a block of 45x45.
308 *
309 *  Test succeeds if centers of generated points have valid colors.
310 *
311 *  2.2. If "lines" output primitive type is used:
312 *
313 *  Expanding on the idea presenting in 2.1, for each line segment the GS
314 *  should generate three line segments, as presented below:
315 *
316 *                       Upper/left helper line segment
317 *                       Line segment
318 *                       Bottom/right helper line segment
319 *
320 *  This is to emulate a larger line width than the minimum maximum line
321 *  width all GLES implementations must support.
322 *
323 *  Upper helper line segment should use start point's color;
324 *  Middle line segment should take mix(start_color, end_color, 0.5) color;
325 *  Bottom helper line segment should use end point's color;
326 *
327 *  Test succeeds if all pixels of generated middle line segments have valid
328 *  colors. Do not test corners.
329 *
330 *  2.3. If "triangles" output primitive type is used:
331 *
332 *  Expanding on the idea presented in 2.1: for each input line segment,
333 *  the GS should generate a triangle, using two vertices provided and
334 *  (0, 0, 0, 1). By drawing a quad outline, whole screen-space should be
335 *  covered with four triangles.
336 *  The test passes if centroids of the generated triangles carry valid colors.
337 *
338 **/
339class GeometryShaderRenderingLinesCase : public GeometryShaderRenderingCase
340{
341public:
342	/* Public methods */
343	GeometryShaderRenderingLinesCase(Context& context, const ExtParameters& extParams, const char* name,
344									 bool use_adjacency_data, glw::GLenum drawcall_mode,
345									 _shader_output_type output_type);
346
347	virtual ~GeometryShaderRenderingLinesCase();
348
349protected:
350	/* GeometryShaderRenderingCase interface implementation */
351	unsigned int getAmountOfDrawInstances();
352	unsigned int getAmountOfElementsPerInstance();
353	unsigned int getAmountOfVerticesPerInstance();
354	glw::GLenum  getDrawCallMode();
355	std::string  getFragmentShaderCode();
356	std::string  getGeometryShaderCode();
357	glw::GLuint getRawArraysDataBufferSize(bool instanced);
358	const void* getRawArraysDataBuffer(bool instanced);
359	void getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, unsigned int* out_height);
360	glw::GLuint getUnorderedArraysDataBufferSize(bool instanced);
361	const void* getUnorderedArraysDataBuffer(bool instanced);
362	glw::GLuint getUnorderedElementsDataBufferSize(bool instanced);
363	const void* getUnorderedElementsDataBuffer(bool instanced);
364	glw::GLenum  getUnorderedElementsDataType();
365	glw::GLubyte getUnorderedElementsMaxIndex();
366	glw::GLubyte getUnorderedElementsMinIndex();
367	std::string  getVertexShaderCode();
368	void setUniformsBeforeDrawCall(_draw_call_type drawcall_type);
369	void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char* data);
370
371private:
372	/* Private variables */
373	_shader_output_type m_output_type;
374
375	glw::GLenum m_drawcall_mode;
376	bool		m_use_adjacency_data;
377
378	float*		 m_raw_array_instanced_data;
379	unsigned int m_raw_array_instanced_data_size;
380	float*		 m_raw_array_noninstanced_data;
381	unsigned int m_raw_array_noninstanced_data_size;
382
383	float*		 m_unordered_array_instanced_data;
384	unsigned int m_unordered_array_instanced_data_size;
385	float*		 m_unordered_array_noninstanced_data;
386	unsigned int m_unordered_array_noninstanced_data_size;
387
388	unsigned char* m_unordered_elements_instanced_data;
389	unsigned int   m_unordered_elements_instanced_data_size;
390	unsigned char* m_unordered_elements_noninstanced_data;
391	unsigned int   m_unordered_elements_noninstanced_data_size;
392
393	unsigned char m_unordered_elements_max_index;
394	unsigned char m_unordered_elements_min_index;
395};
396
397/** Implements Geometry Shader conformance test group 1, 'triangles' and
398 *  'triangles_adjacency' input primitive type cases. Test specification
399 *  for this case follows:
400 *
401 *  All tests should draw a 45-degree rotated square shape consisting of four
402 *  separate triangles, as depicted in the picture below:
403 *
404 *
405 *                                 C
406 *                                / \
407     *                               /   \
408     *                              B--A--D
409 *                               \   /
410 *                                \_/
411 *                                 E
412 *
413 *  For GL_TRIANGLES data, the rendering order is: ABC, ACD, ADE, AEB;
414 *  For GL_TRIANGLE_FAN,   the rendering order is: ABCDEB;
415 *  For GL_TRIANGLE_STRIP, the rendering order is: BACDAEB;
416 *
417 *  Note that for triangle strips, a degenerate triangle will be rendered.
418 *  Test implementation should not test the first triangle rendered in the
419 *  top-right quarter, as it will be overwritten by the triangle that follows
420 *  right after.
421 *
422 *  Subsequent draw call instances should draw the geometry one after another,
423 *  in vertical direction.
424 *
425 *  Each of the tests should use 29x(29 * number of instances) resolution for
426 *  the rendertarget.
427 *
428 *  3.1. If "points" output primitive type is used:
429 *
430 *  The geometry shader should generate 3 points for a single input triangle.
431 *  These points should be emitted for each of the triangle's vertex
432 *  locations and:
433 *
434 *  * First vertex should be of (R, G, B, A) color;
435 *  * Second vertex should be of (R', G', B', A') color;
436 *  * Third vertex should be of (R'', G'', B'', A'') color;
437 *
438 *  Each point should actually consist of 9 emitted points of size 1 (as
439 *  described in test scenario 1.1), with the middle point being positioned
440 *  at exact vertex location. This is to emulate larger point size than the
441 *  minimum maximum allows. All emitted points should use the same color as
442 *  parent point's.
443 *
444 *  Test succeeds if centers of the rendered points have valid colors.
445 *
446 *  3.2. If "lines" output primitive type is used:
447 *
448 *  Let:
449 *
450 *  * TL represent top-left corner of the triangle's bounding box;
451 *  * TR represent top-right corner of the triangle's bounding box;
452 *  * BL represent bottom-left corner of the triangle's bounding box;
453 *  * BR represent bottom-right corner of the triangle's bounding box;
454 *
455 *  The geometry shader should draw 4 line segments for a single input
456 *  triangle:
457 *
458 *  * First line segment should start at BL and end at TL and use a static
459 *    (R, G, B, A) color;
460 *  * Second line segment should start at TL and end at TR and use a static
461 *    (R', G', B', A') color;
462 *  * Third line segment should start at TR and end at BR and use a static
463 *    (R'', G'', B'', A'') color;
464 *  * Fourth line segment should start at BR and end at BL and use a static
465 *    (R, G', B'', A) color;
466 *
467 *  Each line segment should actually consist of 3 separate line segments
468 *  "stacked" on top of each other, with the middle segment being positioned
469 *  as described above (as described in test scenario 2.2). This is to
470 *  emulate line width that is larger than the minimum maximum allows. All
471 *  emitted line segments should use the same color as parent line segment's.
472 *
473 *  Test succeeds if centers of the rendered line segments have valid colors.
474 *
475 *  3.3. If "triangles" output primitive type is used:
476 *
477 *  Test should take incoming triangle vertex locations and order them in the
478 *  following order:
479 *
480 *  a) A - vertex in the origin;
481 *  b) B - the other vertex located on the same height as A;
482 *  c) C - remaining vertex;
483 *
484 *  Let D = BC/2.
485 *
486 *  The test should emit ABD and ACD triangles for input ABC triangle data.
487 *  First triangle emitted should take color of the first input vertex
488 *  (not necessarily A!).
489 *  The second one should use third vertex's color (not necessarily C!),
490 *  with the first channel being multiplied by two.
491 *
492 *  Test succeeds if centers of the rendered triangles have valid colors;
493 *
494 **/
495class GeometryShaderRenderingTrianglesCase : public GeometryShaderRenderingCase
496{
497public:
498	/* Public methods */
499	GeometryShaderRenderingTrianglesCase(Context& context, const ExtParameters& extParams, const char* name,
500										 bool use_adjacency_data, glw::GLenum drawcall_mode,
501										 _shader_output_type output_type);
502
503	virtual ~GeometryShaderRenderingTrianglesCase();
504
505protected:
506	/* GeometryShaderRenderingCase interface implementation */
507	unsigned int getAmountOfDrawInstances();
508	unsigned int getAmountOfElementsPerInstance();
509	unsigned int getAmountOfVerticesPerInstance();
510	glw::GLenum  getDrawCallMode();
511	std::string  getFragmentShaderCode();
512	std::string  getGeometryShaderCode();
513	glw::GLuint getRawArraysDataBufferSize(bool instanced);
514	const void* getRawArraysDataBuffer(bool instanced);
515	void getRenderTargetSize(unsigned int n_instances, unsigned int* out_width, unsigned int* out_height);
516	glw::GLuint getUnorderedArraysDataBufferSize(bool instanced);
517	const void* getUnorderedArraysDataBuffer(bool instanced);
518	glw::GLuint getUnorderedElementsDataBufferSize(bool instanced);
519	const void* getUnorderedElementsDataBuffer(bool instanced);
520	glw::GLenum  getUnorderedElementsDataType();
521	glw::GLubyte getUnorderedElementsMaxIndex();
522	glw::GLubyte getUnorderedElementsMinIndex();
523	std::string  getVertexShaderCode();
524	void setUniformsBeforeDrawCall(_draw_call_type drawcall_type);
525	void verify(_draw_call_type drawcall_type, unsigned int instance_id, const unsigned char* data);
526
527private:
528	/* Private variables */
529	_shader_output_type m_output_type;
530
531	glw::GLenum m_drawcall_mode;
532	bool		m_use_adjacency_data;
533
534	float*		 m_raw_array_instanced_data;
535	unsigned int m_raw_array_instanced_data_size;
536	float*		 m_raw_array_noninstanced_data;
537	unsigned int m_raw_array_noninstanced_data_size;
538
539	float*		 m_unordered_array_instanced_data;
540	unsigned int m_unordered_array_instanced_data_size;
541	float*		 m_unordered_array_noninstanced_data;
542	unsigned int m_unordered_array_noninstanced_data_size;
543
544	unsigned char* m_unordered_elements_instanced_data;
545	unsigned int   m_unordered_elements_instanced_data_size;
546	unsigned char* m_unordered_elements_noninstanced_data;
547	unsigned int   m_unordered_elements_noninstanced_data_size;
548
549	unsigned char m_unordered_elements_max_index;
550	unsigned char m_unordered_elements_min_index;
551};
552
553} // namespace glcts
554
555#endif // _ESEXTCGEOMETRYSHADERRENDERING_HPP
556