• 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 "esextcGeometryShaderPrimitiveQueries.hpp"
25 
26 #include "gluDefs.hpp"
27 #include "glwEnums.hpp"
28 #include "glwFunctions.hpp"
29 #include "tcuTestLog.hpp"
30 
31 namespace glcts
32 {
33 
34 /* Fragment shader */
35 const char* GeometryShaderPrimitiveQueries::m_fs_code = "${VERSION}\n"
36 														"\n"
37 														"precision highp float;\n"
38 														"\n"
39 														"void main()\n"
40 														"{\n"
41 														"}\n";
42 
43 /* Vertex shader */
44 const char* GeometryShaderPrimitiveQueries::m_vs_code = "${VERSION}\n"
45 														"\n"
46 														"precision highp float;\n"
47 														"\n"
48 														"void main()\n"
49 														"{\n"
50 														"    gl_Position = vec4(gl_VertexID, 0, 0, 1);\n"
51 														"}\n";
52 
53 /* Geometry shader */
54 const char* GeometryShaderPrimitiveQueriesPoints::m_gs_code =
55 	"${VERSION}\n"
56 	"\n"
57 	"${GEOMETRY_SHADER_REQUIRE}\n"
58 	"\n"
59 	"precision highp float;\n"
60 	"\n"
61 	"layout(points)                          in;\n"
62 	"layout(points, max_vertices=8)          out;\n"
63 	"\n"
64 	"void main()\n"
65 	"{\n"
66 	"    for (int n = 0; n < 8; ++n)\n"
67 	"    {\n"
68 	"        gl_Position = vec4(1.0 / (float(n) + 1.0), 1.0 / (float(n) + 2.0), 0.0, 1.0);\n"
69 	"        EmitVertex();\n"
70 	"    }\n"
71 	"\n"
72 	"    EndPrimitive();\n"
73 	"}\n";
74 
75 /* Geometry shader */
76 const char* GeometryShaderPrimitiveQueriesLines::m_gs_code =
77 	"${VERSION}\n"
78 	"\n"
79 	"${GEOMETRY_SHADER_REQUIRE}\n"
80 	"\n"
81 	"precision highp float;\n"
82 	"\n"
83 	"layout(points)                          in;\n"
84 	"layout(line_strip, max_vertices=10)     out;\n"
85 	"\n"
86 	"void main()\n"
87 	"{\n"
88 	"    for (int n = 0; n < 10; ++n)\n"
89 	"    {\n"
90 	"        gl_Position = vec4(1.0 / (float(n) + 1.0), 1.0 / (float(n) + 2.0), 0.0, 1.0);\n"
91 	"        EmitVertex();\n"
92 	"    }\n"
93 	"\n"
94 	"    EndPrimitive();\n"
95 	"}\n";
96 
97 /* Geometry shader */
98 const char* GeometryShaderPrimitiveQueriesTriangles::m_gs_code =
99 	"${VERSION}\n"
100 	"\n"
101 	"${GEOMETRY_SHADER_REQUIRE}\n"
102 	"\n"
103 	"precision highp float;\n"
104 	"\n"
105 	"layout(points)                          in;\n"
106 	"layout(triangle_strip, max_vertices=12) out;\n"
107 	"\n"
108 	"void main()\n"
109 	"{\n"
110 	"    for (int n = 0; n < 12; ++n)\n"
111 	"    {\n"
112 	"        gl_Position = vec4(1.0 / (float(n) + 1.0), 1.0 / (float(n) + 2.0), 0.0, 1.0);\n"
113 	"        EmitVertex();\n"
114 	"    }\n"
115 	"\n"
116 	"    EndPrimitive();\n"
117 	"}\n";
118 
119 /** Constructor
120  *
121  * @param context       Test context
122  * @param name          Test case's name
123  * @param description   Test case's description
124  **/
GeometryShaderPrimitiveQueriesPoints(Context & context,const ExtParameters & extParams,const char * name,const char * description)125 GeometryShaderPrimitiveQueriesPoints::GeometryShaderPrimitiveQueriesPoints(Context&				context,
126 																		   const ExtParameters& extParams,
127 																		   const char* name, const char* description)
128 	: GeometryShaderPrimitiveQueries(context, extParams, name, description)
129 {
130 }
131 
132 /** Gets geometry shader code
133  *
134  * @return geometry shader code
135  **/
getGeometryShaderCode()136 const char* GeometryShaderPrimitiveQueriesPoints::getGeometryShaderCode()
137 {
138 	return m_gs_code;
139 }
140 
141 /** Gets the number of emitted vertices
142  *
143  * @return number of emitted vertices
144  **/
getAmountOfEmittedVertices()145 glw::GLint GeometryShaderPrimitiveQueriesPoints::getAmountOfEmittedVertices()
146 {
147 	return 8;
148 }
149 
150 /** Gets the transform feedback mode
151  *
152  * @return transform feedback mode
153  **/
getTFMode()154 glw::GLenum GeometryShaderPrimitiveQueriesPoints::getTFMode()
155 {
156 	return GL_POINTS;
157 }
158 
159 /** Constructor
160  *
161  * @param context       Test context
162  * @param name          Test case's name
163  * @param description   Test case's desricption
164  **/
GeometryShaderPrimitiveQueriesLines(Context & context,const ExtParameters & extParams,const char * name,const char * description)165 GeometryShaderPrimitiveQueriesLines::GeometryShaderPrimitiveQueriesLines(Context&			  context,
166 																		 const ExtParameters& extParams,
167 																		 const char* name, const char* description)
168 	: GeometryShaderPrimitiveQueries(context, extParams, name, description)
169 {
170 }
171 
172 /** Gets geometry shader code
173  *
174  * @return geometry shader code
175  **/
getGeometryShaderCode()176 const char* GeometryShaderPrimitiveQueriesLines::getGeometryShaderCode()
177 {
178 	return m_gs_code;
179 }
180 
181 /** Gets the number of emitted vertices
182  *
183  * @return number of emitted vertices
184  **/
getAmountOfEmittedVertices()185 glw::GLint GeometryShaderPrimitiveQueriesLines::getAmountOfEmittedVertices()
186 {
187 	return 18;
188 }
189 
190 /** Gets the transform feedback mode
191  *
192  * @return transform feedback mode
193  **/
getTFMode()194 glw::GLenum GeometryShaderPrimitiveQueriesLines::getTFMode()
195 {
196 	return GL_LINES;
197 }
198 
199 /** Constructor
200  *
201  * @param context       Test context
202  * @param name          Test case's name
203  * @param description   Test case's desricption
204  **/
GeometryShaderPrimitiveQueriesTriangles(Context & context,const ExtParameters & extParams,const char * name,const char * description)205 GeometryShaderPrimitiveQueriesTriangles::GeometryShaderPrimitiveQueriesTriangles(Context&			  context,
206 																				 const ExtParameters& extParams,
207 																				 const char*		  name,
208 																				 const char*		  description)
209 	: GeometryShaderPrimitiveQueries(context, extParams, name, description)
210 {
211 }
212 
213 /** Gets geometry shader code
214  *
215  * @return geometry shader code
216  **/
getGeometryShaderCode()217 const char* GeometryShaderPrimitiveQueriesTriangles::getGeometryShaderCode()
218 {
219 	return m_gs_code;
220 }
221 
222 /** Gets the number of emitted vertices
223  *
224  * @return number of emitted vertices
225  **/
getAmountOfEmittedVertices()226 glw::GLint GeometryShaderPrimitiveQueriesTriangles::getAmountOfEmittedVertices()
227 {
228 	return 30;
229 }
230 
231 /** Gets the transform feedback mode
232  *
233  * @return transform feedback mode
234  **/
getTFMode()235 glw::GLenum GeometryShaderPrimitiveQueriesTriangles::getTFMode()
236 {
237 	return GL_TRIANGLES;
238 }
239 
240 /** Constructor
241  *
242  * @param context       Test context
243  * @param name          Test case's name
244  * @param description   Test case's desricption
245  **/
GeometryShaderPrimitiveQueries(Context & context,const ExtParameters & extParams,const char * name,const char * description)246 GeometryShaderPrimitiveQueries::GeometryShaderPrimitiveQueries(Context& context, const ExtParameters& extParams,
247 															   const char* name, const char* description)
248 	: TestCaseBase(context, extParams, name, description)
249 	, m_n_texture_components(4)
250 	, m_bo_large_id(0)
251 	, m_bo_small_id(0)
252 	, m_fs_id(0)
253 	, m_gs_id(0)
254 	, m_po_id(0)
255 	, m_qo_primitives_generated_id(0)
256 	, m_qo_tf_primitives_written_id(0)
257 	, m_vao_id(0)
258 	, m_vs_id(0)
259 {
260 	/* Nothing to be done here */
261 }
262 
263 /** Deinitializes GLES objects created during the test.
264  *
265  */
deinit(void)266 void GeometryShaderPrimitiveQueries::deinit(void)
267 {
268 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
269 
270 	/* Reset OpenGL ES state */
271 	gl.useProgram(0);
272 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
273 	gl.bindVertexArray(0);
274 
275 	if (m_po_id != 0)
276 	{
277 		gl.deleteProgram(m_po_id);
278 	}
279 
280 	if (m_fs_id != 0)
281 	{
282 		gl.deleteShader(m_fs_id);
283 	}
284 
285 	if (m_gs_id != 0)
286 	{
287 		gl.deleteShader(m_gs_id);
288 	}
289 
290 	if (m_vs_id != 0)
291 	{
292 		gl.deleteShader(m_vs_id);
293 	}
294 
295 	if (m_bo_small_id != 0)
296 	{
297 		gl.deleteBuffers(1, &m_bo_small_id);
298 	}
299 
300 	if (m_bo_large_id != 0)
301 	{
302 		gl.deleteBuffers(1, &m_bo_large_id);
303 	}
304 
305 	if (m_qo_primitives_generated_id != 0)
306 	{
307 		gl.deleteQueries(1, &m_qo_primitives_generated_id);
308 	}
309 
310 	if (m_qo_tf_primitives_written_id != 0)
311 	{
312 		gl.deleteQueries(1, &m_qo_tf_primitives_written_id);
313 	}
314 
315 	if (m_vao_id != 0)
316 	{
317 		gl.deleteVertexArrays(1, &m_vao_id);
318 	}
319 
320 	/* Release base class */
321 	TestCaseBase::deinit();
322 }
323 
324 /** Executes the test.
325  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
326  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
327  *  Note the function throws exception should an error occur!
328  **/
iterate(void)329 tcu::TestNode::IterateResult GeometryShaderPrimitiveQueries::iterate(void)
330 {
331 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
332 
333 	/* Check if geometry_shader extension is supported */
334 	if (!m_is_geometry_shader_extension_supported)
335 	{
336 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
337 	}
338 
339 	/* Create shader objects and a program object */
340 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
341 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
342 	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
343 	m_po_id = gl.createProgram();
344 
345 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program/shader objects.");
346 
347 	/* Try to build test-specific program object */
348 	const char* tf_varyings[] = { "gl_Position" };
349 	const char* gs_code		  = getGeometryShaderCode();
350 
351 	gl.transformFeedbackVaryings(m_po_id, sizeof(tf_varyings) / sizeof(tf_varyings[0]), tf_varyings,
352 								 GL_SEPARATE_ATTRIBS);
353 
354 	if (!buildProgram(m_po_id, m_fs_id, 1 /* part */, &m_fs_code, m_gs_id, 1 /* part */, &gs_code, m_vs_id,
355 					  1 /* part */, &m_vs_code))
356 	{
357 		TCU_FAIL("Could not create a program for GeometryShaderPrimitiveQueries!");
358 	}
359 
360 	/* Create and bind a vertex array object */
361 	gl.genVertexArrays(1, &m_vao_id);
362 	gl.bindVertexArray(m_vao_id);
363 
364 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating a vertex array object.");
365 
366 	/* Create two buffer objects
367 	 *
368 	 * One with sufficiently large storage space to hold position data for particular output.
369 	 * Another one of insufficient size.
370 	 */
371 	gl.genBuffers(1, &m_bo_large_id);
372 	gl.genBuffers(1, &m_bo_small_id);
373 
374 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_large_id);
375 	gl.bufferData(GL_ARRAY_BUFFER,
376 				  getAmountOfEmittedVertices() * m_n_texture_components /* components */ * sizeof(float), NULL,
377 				  GL_STATIC_DRAW);
378 
379 	gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_small_id);
380 	gl.bufferData(GL_ARRAY_BUFFER,
381 				  (getAmountOfEmittedVertices() / 2) * m_n_texture_components /* components */ * sizeof(float), NULL,
382 				  GL_STATIC_DRAW);
383 
384 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error allocating buffer objects.");
385 
386 	/* Create primitive query objects */
387 	gl.genQueries(1, &m_qo_tf_primitives_written_id);
388 	gl.genQueries(1, &m_qo_primitives_generated_id);
389 
390 	glw::GLuint nPrimitivesGenerated = 0;
391 	glw::GLuint nTFPrimitivesWritten = 0;
392 
393 	/* Test case 13.1 */
394 	readPrimitiveQueryValues(m_bo_large_id, &nPrimitivesGenerated, &nTFPrimitivesWritten);
395 
396 	if (nPrimitivesGenerated == 0)
397 	{
398 		m_testCtx.getLog()
399 			<< tcu::TestLog::Message
400 			<< "Retrieved GL_PRIMITIVES_GENERATED_EXT query object value is zero which should never happen."
401 			<< tcu::TestLog::EndMessage;
402 
403 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
404 		return STOP;
405 	}
406 
407 	if (nTFPrimitivesWritten == 0)
408 	{
409 		m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query "
410 													   "object value is zero which should never happen."
411 						   << tcu::TestLog::EndMessage;
412 
413 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
414 		return STOP;
415 	}
416 
417 	if (nPrimitivesGenerated != nTFPrimitivesWritten)
418 	{
419 		m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved GL_PRIMITIVES_GENERATED_EXT query object value("
420 						   << nPrimitivesGenerated
421 						   << ") is different than for GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN ("
422 						   << nTFPrimitivesWritten << ")" << tcu::TestLog::EndMessage;
423 
424 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
425 		return STOP;
426 	}
427 
428 	/* Test case 13.2 */
429 	nPrimitivesGenerated = 0;
430 	nTFPrimitivesWritten = 0;
431 
432 	readPrimitiveQueryValues(m_bo_small_id, &nPrimitivesGenerated, &nTFPrimitivesWritten);
433 
434 	if (nPrimitivesGenerated == 0)
435 	{
436 		m_testCtx.getLog()
437 			<< tcu::TestLog::Message
438 			<< "Retrieved GL_PRIMITIVES_GENERATED_EXT query object value is zero which should never happen."
439 			<< tcu::TestLog::EndMessage;
440 
441 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
442 		return STOP;
443 	}
444 
445 	if (nTFPrimitivesWritten == 0)
446 	{
447 		m_testCtx.getLog() << tcu::TestLog::Message << "Retrieved GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query "
448 													   "object value is zero which should never happen."
449 						   << tcu::TestLog::EndMessage;
450 
451 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
452 		return STOP;
453 	}
454 
455 	if ((nPrimitivesGenerated / 2) != nTFPrimitivesWritten)
456 	{
457 		m_testCtx.getLog() << tcu::TestLog::Message
458 						   << "Retrieved GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query object value("
459 						   << nPrimitivesGenerated << ") should be half the amount of GL_PRIMITIVES_GENERATED_EXT ("
460 						   << nTFPrimitivesWritten << ")" << tcu::TestLog::EndMessage;
461 
462 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
463 		return STOP;
464 	}
465 
466 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
467 	return STOP;
468 }
469 
470 /**
471  * The function binds the provided bufferId to transform feedback target and sets up a query
472  * for GL_PRIMITIVES_GENERATED_EXT GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN.
473  * It then issues a draw call to execute the vertex and geometry shaders. Then results
474  * of the queries are written to nPrimitivesGenerated and nPrimitivesWritten variables.
475  *
476  * @param context bufferId   id of the buffer to be bound to transform feedback target
477  * @return nPrimitivesGenerated      the result of GL_PRIMITIVES_GENERATED_EXT query
478  * @return nPrimitivesWritten        the result of GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query
479  */
readPrimitiveQueryValues(glw::GLint bufferId,glw::GLuint * nPrimitivesGenerated,glw::GLuint * nPrimitivesWritten)480 void GeometryShaderPrimitiveQueries::readPrimitiveQueryValues(glw::GLint bufferId, glw::GLuint* nPrimitivesGenerated,
481 															  glw::GLuint* nPrimitivesWritten)
482 {
483 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
484 
485 	/* Bind the buffer object to hold the captured data.*/
486 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bufferId);
487 
488 	/* Activate the program object */
489 	gl.useProgram(m_po_id);
490 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error using program object");
491 
492 	gl.beginTransformFeedback(getTFMode());
493 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error starting transform feedback");
494 
495 	/* Activate the queries */
496 	gl.beginQuery(m_glExtTokens.PRIMITIVES_GENERATED, m_qo_primitives_generated_id);
497 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error starting GL_PRIMITIVES_GENERATED_EXT query");
498 
499 	gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_qo_tf_primitives_written_id);
500 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error starting GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN query");
501 
502 	/* Render */
503 	gl.drawArrays(GL_POINTS, 0 /* first */, 1 /* count */);
504 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error executing draw call");
505 
506 	gl.endTransformFeedback();
507 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error finishing transform feedback");
508 
509 	/* Query objects end here. */
510 	gl.endQuery(m_glExtTokens.PRIMITIVES_GENERATED);
511 	gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
512 
513 	/* Retrieve query values */
514 	gl.getQueryObjectuiv(m_qo_primitives_generated_id, GL_QUERY_RESULT, nPrimitivesGenerated);
515 	gl.getQueryObjectuiv(m_qo_tf_primitives_written_id, GL_QUERY_RESULT, nPrimitivesWritten);
516 
517 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error retrieving query values.");
518 }
519 
520 } // namespace glcts
521