1#ifndef _ESEXTCGEOMETRYSHADERPRIMITIVECOUNTER_HPP
2#define _ESEXTCGEOMETRYSHADERPRIMITIVECOUNTER_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 <string.h>
28
29namespace glcts
30{
31
32struct DataPrimitiveIDInCounter
33{
34	glw::GLenum m_drawMode;
35	std::string m_emitVertexCodeForGeometryShader;
36	glw::GLenum m_feedbackMode;
37	std::string m_layoutIn;
38	std::string m_layoutOut;
39	glw::GLuint m_numberOfVerticesPerOneOutputPrimitive;
40	glw::GLuint m_numberOfVerticesPerOneInputPrimitive;
41	glw::GLuint m_numberOfDrawnPrimitives;
42};
43
44/** Implementation of "Group 6" from CTS_EXT_geometry_shader.
45 *   Test Group for "Group 6" tests, storing configuration data and initializing the tests.
46 *   All tests from "Group 6" and children of GeometryShaderPrimitiveCounterTestGroup.
47 */
48class GeometryShaderPrimitiveCounterTestGroup : public TestCaseGroupBase
49{
50public:
51	/* Public methods */
52	GeometryShaderPrimitiveCounterTestGroup(Context& context, const ExtParameters& extParams, const char* name,
53											const char* description);
54
55	virtual ~GeometryShaderPrimitiveCounterTestGroup()
56	{
57	}
58
59	virtual void init(void);
60};
61
62/**
63 * 1. Make sure that a built-in geometry shader's input variable
64 *    gl_PrimitiveIDIn increments correctly for all valid <draw call mode,
65 *    input primitive type, output primitive type> tuples.
66 "
67 *    Category: API;
68 *              Functional Test.
69 *
70 *    Let N_VERTICES represent amount of vertices that must be emitted, given
71 *    active geometry shader's output primitive type, to form a single
72 *    primitive that can be passed to rasterization stage
73 *
74 *    Use Transform Feedback functionality to capture gl_PrimitiveIDIn value
75 *    as read in the geometry shader:
76 *
77 *    - The shader should emit:
78 *
79 *      floor(GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT / N_VERTICES) / (4 + 1)
80 *
81 *      primitives. It should call EndPrimitive() every N_VERTICES vertices
82 *      emitted.
83 *
84 *    - The draw call should be made for 1024 primitives.
85 *
86 *    Test should fail if the result data for any of the tuples is determined
87 *    to be incorrect.
88 */
89class GeometryShaderPrimitiveCounter : public TestCaseBase
90{
91public:
92	/* Public methods */
93	GeometryShaderPrimitiveCounter(Context& context, const ExtParameters& extParams, const char* name,
94								   const char* description, const DataPrimitiveIDInCounter& testConfiguration);
95
96	virtual ~GeometryShaderPrimitiveCounter(void)
97	{
98	}
99
100	virtual void		  deinit(void);
101	virtual IterateResult iterate(void);
102
103protected:
104	/* Protected methods */
105	bool checkResult(const glw::GLint* feedbackResult);
106	void createAndBuildProgramWithFeedback(void);
107	void drawAndGetFeedback(glw::GLint* feedbackResult);
108	void prepareBufferObjects();
109
110	/* Protected virtual methods */
111	virtual void drawFunction();
112
113	/* Protected members */
114	DataPrimitiveIDInCounter m_testConfiguration;
115
116	glw::GLuint m_nrVaryings;
117	glw::GLuint m_sizeOfDataArray;
118	glw::GLuint m_sizeOfFeedbackBuffer;
119
120	const glw::GLuint m_n_components;
121
122private:
123	/* Private functions */
124	std::string GetGeometryShaderCode(const std::string& max_vertices, const std::string& layout_in,
125									  const std::string& layout_out, const std::string& emit_vertices,
126									  const std::string& n_iterations);
127
128	/* Private variables */
129	static const char* m_fragment_shader_code;
130	static const char* m_vertex_shader_code;
131
132	glw::GLint m_maxGeometryOutputVertices;
133
134	glw::GLuint m_fragment_shader_id;
135	glw::GLuint m_geometry_shader_id;
136	glw::GLuint m_vertex_shader_id;
137	glw::GLuint m_program_id;
138
139	glw::GLuint m_tbo;
140	glw::GLuint m_vao;
141	glw::GLuint m_vbo;
142};
143
144/** 2. Make sure that restarting a primitive topology with a primitive restart
145 *     index does not affect primitive ID counter, when a element-driven draw
146 *     call is made.
147 *
148 *     Category: API;
149 *               Functional Test.
150 *
151 *     Modify test case 6.1 so that it uses element-sourced data. Insert the
152 *     restart primitive index right after first primitive is rendered but
153 *     before indices for the second one start.
154 */
155class GeometryShaderPrimitiveCounterRestartingPrimitive : public GeometryShaderPrimitiveCounter
156{
157public:
158	/* Public methods */
159	GeometryShaderPrimitiveCounterRestartingPrimitive(Context& context, const ExtParameters& extParams,
160													  const char* name, const char* description,
161													  const DataPrimitiveIDInCounter& testConfiguration);
162
163	virtual ~GeometryShaderPrimitiveCounterRestartingPrimitive(void)
164	{
165	}
166
167	virtual void		  deinit(void);
168	virtual IterateResult iterate(void);
169
170protected:
171	/* Protected functions */
172	virtual void drawFunction();
173	void		 setUpVertexAttributeArrays();
174
175private:
176	/* Private fields */
177	glw::GLuint m_bo_id;
178	glw::GLuint m_numberOfRestarts;
179};
180
181/** 3. Make sure that gl_PrimitiveID built-in variable can be read correctly
182 *      from a fragment shader, assuming geometry shader writes to it in
183 *      previous stage.
184 *
185 *      Category: API;
186 *                Functional Test.
187 *
188 *      Vertex shader should output an int variable called vs_vertex_id, to which
189 *      gl_VertexID has been saved.
190 *
191 *      Geometry shader should take points and output a triangle strip. It will
192 *      emit up to 4 vertices. The geometry shader should define an input int
193 *      variable called vs_vertex_id. Let:
194 *
195 *      int column = vs_vertex_id % 64;
196 *      int row = floor(vs_vertex_id / 64);
197 *
198 *      The shader should emit the following vertices:
199 *
200 *      1) (-1.0 + (column+1) / 32.0, -1.0 + (row + 1) / 32.0, 0, 1)
201 *      2) (-1.0 + (column+1) / 32.0, -1.0 + (row)     / 32.0, 0, 1)
202 *      3) (-1.0 + (column)   / 32.0, -1.0 + (row + 1) / 32.0, 0, 1)
203 *      4) (-1.0 + (column)   / 32.0, -1.0 + (row)     / 32.0, 0, 1)
204 *
205 *      Finally, the geometry shader should set gl_PrimitiveID for each of the
206 *      vertices to vs_vertex_id.
207 *
208 *      Fragment shader should set output variable's result value as follows: (*)
209 *
210 *      result[0] =      (gl_PrimitiveID % 64) / 64.0;
211 *      result[1] = floor(gl_PrimitiveID / 64) / 64.0;
212 *      result[2] =       gl_PrimitiveID       / 4096.0;
213 *      result[3] = ((gl_PrimitiveID % 2) == 0) ? 1.0 : 0.0;
214 *
215 *      Using a program object built of these shader, the test should issue
216 *      a draw call for 4096 points. The test is considered to have passed
217 *      successfully if the rendered data consists of 4096 rectangles of edge
218 *      equal to 1/64th of the output resolution, centers of which have values
219 *      as described in (*).
220 *
221 *      Texture object used as color attachment should be at least of 1024x1024
222 *      resolution, in which case quad edge will be 4px long.
223 */
224class GeometryShaderPrimitiveIDFromFragmentShader : public TestCaseBase
225{
226public:
227	/* Publi methods */
228	GeometryShaderPrimitiveIDFromFragmentShader(Context& context, const ExtParameters& extParams, const char* name,
229												const char* description);
230
231	virtual ~GeometryShaderPrimitiveIDFromFragmentShader(void)
232	{
233	}
234
235	void		  deinit(void);
236	IterateResult iterate(void);
237
238private:
239	/* Private fields */
240	static const char* m_fragment_shader_code;
241	static const char* m_geometry_shader_code;
242	static const char* m_vertex_shader_code;
243
244	const glw::GLuint m_n_drawn_vertices;
245	const glw::GLuint m_squareEdgeSize;
246	const glw::GLuint m_texture_height;
247	const glw::GLuint m_texture_n_components;
248	const glw::GLuint m_texture_n_levels;
249	const glw::GLuint m_texture_width;
250
251	glw::GLuint m_fbo_id;
252	glw::GLuint m_fragment_shader_id;
253	glw::GLuint m_geometry_shader_id;
254	glw::GLuint m_program_id;
255	glw::GLuint m_texture_id;
256	glw::GLuint m_vao_id;
257	glw::GLuint m_vbo_id;
258	glw::GLuint m_vertex_shader_id;
259};
260
261} // namespace glcts
262
263#endif // _ESEXTCGEOMETRYSHADERPRIMITIVECOUNTER_HPP
264