• 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 "gluDefs.hpp"
25 #include "glwEnums.hpp"
26 #include "glwFunctions.hpp"
27 #include "tcuTestLog.hpp"
28 
29 #include "esextcGeometryShaderAdjacency.hpp"
30 #include <math.h>
31 
32 namespace glcts
33 {
34 /** Constructor
35  *
36  **/
AdjacencyGrid()37 AdjacencyGrid::AdjacencyGrid()
38 	: m_line_segments(0), m_points(0), m_triangles(0), m_n_points(0), m_n_segments(0), m_n_triangles(0)
39 {
40 	/* Nothing to be done here */
41 }
42 
43 /** Destructor
44  *
45  **/
~AdjacencyGrid()46 AdjacencyGrid::~AdjacencyGrid()
47 {
48 	if (m_line_segments)
49 	{
50 		delete[] m_line_segments;
51 		m_line_segments = 0;
52 	}
53 
54 	if (m_points)
55 	{
56 		delete[] m_points;
57 		m_points = 0;
58 	}
59 
60 	if (m_triangles)
61 	{
62 		delete[] m_triangles;
63 		m_triangles = 0;
64 	}
65 }
66 
67 /** Constructor
68  *
69  **/
AdjacencyGridStrip()70 AdjacencyGridStrip::AdjacencyGridStrip() : m_n_points(0), m_points(0)
71 {
72 	/* Nothing to be done here */
73 }
74 
75 /** Destructor
76  *
77  **/
~AdjacencyGridStrip()78 AdjacencyGridStrip::~AdjacencyGridStrip()
79 {
80 	if (m_points)
81 	{
82 		delete[] m_points;
83 	}
84 }
85 
86 /** Constructor
87  *
88  **/
AdjacencyTestData()89 AdjacencyTestData::AdjacencyTestData()
90 	: m_gs_code(0)
91 	, m_mode(0)
92 	, m_n_vertices(0)
93 	, m_grid(0)
94 	, m_geometry_bo_size(0)
95 	, m_index_data_bo_size(0)
96 	, m_vertex_data_bo_size(0)
97 	, m_expected_adjacency_geometry(0)
98 	, m_expected_geometry(0)
99 	, m_alternate_expected_adjacency_geometry(0)
100 	, m_alternate_expected_geometry(0)
101 	, m_index_data(0)
102 	, m_tf_mode(0)
103 	, m_vertex_data(0)
104 {
105 	/* Nothing to be done here */
106 }
107 
108 /** Destructor
109  *
110  **/
~AdjacencyTestData()111 AdjacencyTestData::~AdjacencyTestData()
112 {
113 	if (m_expected_adjacency_geometry)
114 	{
115 		delete[] m_expected_adjacency_geometry;
116 		m_expected_adjacency_geometry = 0;
117 	}
118 
119 	if (m_expected_geometry)
120 	{
121 		delete[] m_expected_geometry;
122 		m_expected_geometry = 0;
123 	}
124 
125 	if (m_alternate_expected_adjacency_geometry)
126 	{
127 		delete[] m_alternate_expected_adjacency_geometry;
128 		m_alternate_expected_adjacency_geometry = 0;
129 	}
130 
131 	if (m_alternate_expected_geometry)
132 	{
133 		delete[] m_alternate_expected_geometry;
134 		m_alternate_expected_geometry = 0;
135 	}
136 
137 	if (m_vertex_data)
138 	{
139 		delete[] m_vertex_data;
140 		m_vertex_data = 0;
141 	}
142 
143 	if (m_index_data)
144 	{
145 		delete[] m_index_data;
146 		m_index_data = 0;
147 	}
148 
149 	if (m_grid)
150 	{
151 		delete m_grid;
152 		m_grid = 0;
153 	}
154 }
155 
156 /** Constructor
157  *
158  * @param context       Test context
159  * @param name          Test case's name
160  * @param description   Test case's desricption
161  **/
GeometryShaderAdjacency(Context & context,const ExtParameters & extParams,const char * name,const char * description,AdjacencyTestData & testData)162 GeometryShaderAdjacency::GeometryShaderAdjacency(Context& context, const ExtParameters& extParams, const char* name,
163 												 const char* description, AdjacencyTestData& testData)
164 	: TestCaseBase(context, extParams, name, description)
165 	, m_adjacency_geometry_bo_id(0)
166 	, m_fs_id(0)
167 	, m_geometry_bo_id(0)
168 	, m_gs_id(0)
169 	, m_index_data_bo_id(0)
170 	, m_vertex_data_bo_id(0)
171 	, m_po_id(0)
172 	, m_test_data(testData)
173 	, m_vao_id(0)
174 	, m_vs_id(0)
175 	, m_components_input(2)
176 	, m_epsilon(0.00001F)
177 	, m_position_attribute_location(0)
178 {
179 	/* Nothing to be done here */
180 }
181 
182 /** Deinitializes GLES objects created during the test.
183  *
184  */
deinit(void)185 void GeometryShaderAdjacency::deinit(void)
186 {
187 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
188 
189 	/* Reset OpenGL ES state */
190 	gl.useProgram(0);
191 	gl.bindVertexArray(0);
192 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
193 	gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, 0);
194 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
195 
196 	if (m_po_id != 0)
197 	{
198 		gl.deleteProgram(m_po_id);
199 	}
200 
201 	if (m_fs_id != 0)
202 	{
203 		gl.deleteShader(m_fs_id);
204 	}
205 
206 	if (m_gs_id != 0)
207 	{
208 		gl.deleteShader(m_gs_id);
209 	}
210 
211 	if (m_vs_id != 0)
212 	{
213 		gl.deleteShader(m_vs_id);
214 	}
215 
216 	if (m_adjacency_geometry_bo_id != 0)
217 	{
218 		gl.deleteBuffers(1, &m_adjacency_geometry_bo_id);
219 	}
220 	if (m_geometry_bo_id != 0)
221 	{
222 		gl.deleteBuffers(1, &m_geometry_bo_id);
223 	}
224 
225 	if (m_index_data_bo_id != 0)
226 	{
227 		gl.deleteBuffers(1, &m_index_data_bo_id);
228 	}
229 
230 	if (m_vertex_data_bo_id != 0)
231 	{
232 		gl.deleteBuffers(1, &m_vertex_data_bo_id);
233 	}
234 
235 	if (m_vao_id != 0)
236 	{
237 		gl.deleteVertexArrays(1, &m_vao_id);
238 	}
239 
240 	TestCaseBase::deinit();
241 }
242 
243 /** Returns code for Fragment Shader
244  * @return pointer to literal with Fragment Shader code
245  **/
getFragmentShaderCode()246 const char* GeometryShaderAdjacency::getFragmentShaderCode()
247 {
248 	static const char* result = "${VERSION}\n"
249 								"\n"
250 								"precision highp float;\n"
251 								"\n"
252 								"void main()\n"
253 								"{\n"
254 								"}\n";
255 	return result;
256 }
257 
258 /** Returns code for Vertex Shader
259  * @return pointer to literal with Vertex Shader code
260  **/
getVertexShaderCode()261 const char* GeometryShaderAdjacency::getVertexShaderCode()
262 {
263 	static const char* result = "${VERSION}\n"
264 								"\n"
265 								"precision highp float;\n"
266 								"\n"
267 								"layout(location = 0) in vec2 position_data;\n"
268 								"\n"
269 								"void main()\n"
270 								"{\n"
271 								"    gl_Position = vec4(position_data, 0, 1);\n"
272 								"}\n";
273 	return result;
274 }
275 
276 /** Initializes GLES objects used during the test.
277  *
278  **/
initTest(void)279 void GeometryShaderAdjacency::initTest(void)
280 {
281 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
282 
283 	/* check if EXT_geometry_shader extension is supported */
284 	if (!m_is_geometry_shader_extension_supported)
285 	{
286 		throw tcu::NotSupportedError(GEOMETRY_SHADER_EXTENSION_NOT_SUPPORTED, "", __FILE__, __LINE__);
287 	}
288 
289 	gl.genVertexArrays(1, &m_vao_id);
290 	GLU_EXPECT_NO_ERROR(gl.getError(), "Could not generate vertex array object");
291 
292 	/* Get shader code */
293 	const char* fsCode = getFragmentShaderCode();
294 	const char* gsCode = m_test_data.m_gs_code;
295 	const char* vsCode = getVertexShaderCode();
296 
297 	/* Create shader and program objects */
298 	m_fs_id = gl.createShader(GL_FRAGMENT_SHADER);
299 	m_vs_id = gl.createShader(GL_VERTEX_SHADER);
300 	m_gs_id = gl.createShader(m_glExtTokens.GEOMETRY_SHADER);
301 	m_po_id = gl.createProgram();
302 
303 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error creating program/shader objects.");
304 
305 	/* If gs code is available set gs out data for transformfeedback*/
306 	if (m_test_data.m_gs_code)
307 	{
308 		const char* varyings[] = { "out_adjacent_geometry", "out_geometry" };
309 
310 		gl.transformFeedbackVaryings(m_po_id, 2, varyings, GL_SEPARATE_ATTRIBS);
311 	}
312 	else
313 	{
314 		const char* varyings[] = { "gl_Position" };
315 
316 		gl.transformFeedbackVaryings(m_po_id, 1, varyings, GL_SEPARATE_ATTRIBS);
317 	}
318 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex array object!");
319 
320 	/* Build program */
321 	if (!buildProgram(m_po_id, m_fs_id, 1, /* parts */ &fsCode, (gsCode) ? m_gs_id : 0, (gsCode) ? 1 : 0,
322 					  (gsCode) ? &gsCode : 0, m_vs_id, 1, /* parts */ &vsCode))
323 	{
324 		TCU_FAIL("Could not create a program object from a valid shader!");
325 	}
326 
327 	/* Generate buffers for input/output vertex data */
328 	gl.genBuffers(1, &m_vertex_data_bo_id);
329 	gl.genBuffers(1, &m_adjacency_geometry_bo_id);
330 	gl.genBuffers(1, &m_geometry_bo_id);
331 
332 	/* Configure buffers for input/output vertex data */
333 	gl.bindBuffer(GL_ARRAY_BUFFER, m_adjacency_geometry_bo_id);
334 	gl.bufferData(GL_ARRAY_BUFFER, m_test_data.m_geometry_bo_size * 4, 0, GL_DYNAMIC_DRAW);
335 	gl.bindBuffer(GL_ARRAY_BUFFER, m_geometry_bo_id);
336 	gl.bufferData(GL_ARRAY_BUFFER, m_test_data.m_geometry_bo_size * 4, 0, GL_DYNAMIC_DRAW);
337 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vertex_data_bo_id);
338 	gl.bufferData(GL_ARRAY_BUFFER, m_test_data.m_vertex_data_bo_size, m_test_data.m_vertex_data, GL_DYNAMIC_DRAW);
339 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
340 
341 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex buffer objects for vertex data!");
342 
343 	/* Configure buffer for index data */
344 	if (m_test_data.m_index_data_bo_size > 0)
345 	{
346 		gl.genBuffers(1, &m_index_data_bo_id);
347 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_data_bo_id);
348 		gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, m_test_data.m_index_data_bo_size, m_test_data.m_index_data,
349 					  GL_DYNAMIC_DRAW);
350 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
351 
352 		GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring vertex buffer objects for index data!");
353 	}
354 }
355 
356 /** Executes the test.
357  *  Sets the test result to QP_TEST_RESULT_FAIL if the test failed, QP_TEST_RESULT_PASS otherwise.
358  *  @return STOP if the test has finished, CONTINUE to indicate iterate should be called once again.
359  *  Note the function throws exception should an error occur!
360  **/
iterate(void)361 tcu::TestNode::IterateResult GeometryShaderAdjacency::iterate(void)
362 {
363 	initTest();
364 
365 	const glw::Functions& gl = m_context.getRenderContext().getFunctions();
366 
367 	/** Bind a vertex array object */
368 	gl.bindVertexArray(m_vao_id);
369 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding vertex array object!");
370 
371 	/* Bind buffer objects used as data store for transform feedback to TF binding points*/
372 	if (m_test_data.m_gs_code)
373 	{
374 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_adjacency_geometry_bo_id);
375 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_geometry_bo_id);
376 	}
377 	else
378 	{
379 		gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_geometry_bo_id);
380 	}
381 
382 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error configuring transform feedback buffer binding points!");
383 
384 	gl.bindBuffer(GL_ARRAY_BUFFER, m_vertex_data_bo_id);
385 	m_position_attribute_location = gl.getAttribLocation(m_po_id, "position_data");
386 	gl.vertexAttribPointer(m_position_attribute_location, m_components_input, GL_FLOAT, GL_FALSE, 0, 0);
387 	gl.enableVertexAttribArray(m_position_attribute_location);
388 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error setting vertex attribute array for position_data attribute");
389 
390 	/* bind index buffer */
391 	if (m_test_data.m_index_data_bo_size > 0)
392 	{
393 		gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_index_data_bo_id);
394 	}
395 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error binding index data buffer");
396 
397 	/* Configure program */
398 	gl.enable(GL_RASTERIZER_DISCARD);
399 	gl.useProgram(m_po_id);
400 	gl.beginTransformFeedback(m_test_data.m_tf_mode);
401 
402 	glw::GLuint nVertices = m_test_data.m_n_vertices * ((m_test_data.m_mode == m_glExtTokens.LINE_STRIP_ADJACENCY ||
403 														 m_test_data.m_mode == m_glExtTokens.TRIANGLE_STRIP_ADJACENCY) ?
404 															1 :
405 															2 /* include adjacency info */);
406 
407 	/* Use glDrawElements if data is indicied */
408 	if (m_test_data.m_index_data_bo_size > 0)
409 	{
410 		gl.drawElements(m_test_data.m_mode, nVertices, GL_UNSIGNED_INT, 0);
411 	}
412 	/* Use glDrawArrays if data is non indicied */
413 	else
414 	{
415 		gl.drawArrays(m_test_data.m_mode, 0, nVertices);
416 	}
417 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error while trying to render");
418 
419 	gl.disable(GL_RASTERIZER_DISCARD);
420 	gl.endTransformFeedback();
421 
422 	/* Map result buffer objects into client space */
423 	float* result_adjacency_geometry_ptr = 0;
424 	float* result_geometry_ptr			 = 0;
425 
426 	bool hasAlternateData = m_test_data.m_alternate_expected_geometry != nullptr &&
427 							m_test_data.m_alternate_expected_adjacency_geometry != nullptr;
428 	bool adjacentMatchesExpected		  = true;
429 	bool adjacentMatchesAlternateExpected = hasAlternateData;
430 
431 	/* If gs is available read adjacency data using TF and compare with expected data*/
432 	if (m_test_data.m_gs_code)
433 	{
434 		gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_adjacency_geometry_bo_id);
435 		result_adjacency_geometry_ptr =
436 			(float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_test_data.m_geometry_bo_size, GL_MAP_READ_BIT);
437 		GLU_EXPECT_NO_ERROR(gl.getError(), "Error when mapping data to client space");
438 
439 		std::stringstream sstreamExpected;
440 		std::stringstream sstreamAlternateExpected;
441 		std::stringstream sstreamResult;
442 		sstreamExpected << "[";
443 		if (hasAlternateData)
444 			sstreamAlternateExpected << "[";
445 		sstreamResult << "[";
446 
447 		unsigned int differentExpectedIndex			 = 0;
448 		unsigned int differentAlternateExpectedIndex = 0;
449 		for (unsigned int n = 0; n < m_test_data.m_geometry_bo_size / sizeof(float); ++n)
450 		{
451 			sstreamExpected << m_test_data.m_expected_adjacency_geometry[n] << ", ";
452 			if (hasAlternateData)
453 				sstreamAlternateExpected << m_test_data.m_alternate_expected_adjacency_geometry[n] << ", ";
454 			sstreamResult << result_adjacency_geometry_ptr[n] << ", ";
455 
456 			if (adjacentMatchesExpected &&
457 				de::abs(result_adjacency_geometry_ptr[n] -
458 									   m_test_data.m_expected_adjacency_geometry[n]) >= m_epsilon)
459 			{
460 				adjacentMatchesExpected = false;
461 				differentExpectedIndex = n;
462 			}
463 			if (adjacentMatchesAlternateExpected &&
464 				de::abs(result_adjacency_geometry_ptr[n] - m_test_data.m_alternate_expected_adjacency_geometry[n]) >=
465 					m_epsilon)
466 			{
467 				adjacentMatchesAlternateExpected = false;
468 				differentAlternateExpectedIndex = n;
469 			}
470 			if (!adjacentMatchesExpected && !adjacentMatchesAlternateExpected)
471 			{
472 				gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
473 
474 				m_testCtx.getLog() << tcu::TestLog::Message << "At [" << differentExpectedIndex
475 								   << "] position adjacency buffer position Reference value is different than the "
476 									  "rendered data (epsilon "
477 								   << m_epsilon << " )"
478 								   << " (" << m_test_data.m_expected_adjacency_geometry[differentExpectedIndex]
479 								   << ") vs "
480 								   << "(" << result_adjacency_geometry_ptr[differentExpectedIndex] << ")"
481 								   << tcu::TestLog::EndMessage;
482 
483 				if (hasAlternateData)
484 				{
485 					m_testCtx.getLog()
486 						<< tcu::TestLog::Message << "At [" << differentAlternateExpectedIndex
487 						<< "] alternate position adjacency buffer position Reference value is different than the "
488 						   "rendered data (epsilon "
489 						<< m_epsilon << " )"
490 						<< " (" << m_test_data.m_alternate_expected_adjacency_geometry[differentAlternateExpectedIndex]
491 						<< ") vs "
492 						<< "(" << result_adjacency_geometry_ptr[differentAlternateExpectedIndex] << ")"
493 						<< tcu::TestLog::EndMessage;
494 				}
495 
496 				m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
497 				return STOP;
498 			}
499 		}
500 
501 		sstreamExpected << "]";
502 		if (hasAlternateData)
503 			sstreamAlternateExpected << "]";
504 		sstreamResult << "]";
505 		m_testCtx.getLog() << tcu::TestLog::Message << "Adjacency Expected: " << sstreamExpected.str().c_str()
506 						   << tcu::TestLog::EndMessage;
507 		if (hasAlternateData)
508 			m_testCtx.getLog() << tcu::TestLog::Message
509 							   << "Alternate adjacency Expected: " << sstreamAlternateExpected.str().c_str()
510 							   << tcu::TestLog::EndMessage;
511 		m_testCtx.getLog() << tcu::TestLog::Message << "Adjacency Result:  " << sstreamResult.str().c_str()
512 						   << tcu::TestLog::EndMessage;
513 
514 		gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
515 	}
516 
517 	/* Read vertex data using TF and compare with expected data*/
518 	gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_geometry_bo_id);
519 	result_geometry_ptr =
520 		(float*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_test_data.m_geometry_bo_size, GL_MAP_READ_BIT);
521 	GLU_EXPECT_NO_ERROR(gl.getError(), "Error when mapping data to client space");
522 
523 	std::stringstream sstreamExpected;
524 	std::stringstream sstreamAlternateExpected;
525 	std::stringstream sstreamResult;
526 	sstreamExpected << "[";
527 	if (hasAlternateData)
528 	{
529 		sstreamAlternateExpected << "[";
530 	}
531 	sstreamResult << "[";
532 
533 	bool		 matchesExpected		  = true;
534 	bool		 matchesAlternateExpected = hasAlternateData;
535 	unsigned int differentIndex			  = 0;
536 	unsigned int differentAlternateIndex  = 0;
537 
538 	for (unsigned int n = 0; n < m_test_data.m_geometry_bo_size / sizeof(float); ++n)
539 	{
540 		sstreamExpected << m_test_data.m_expected_geometry[n] << ", ";
541 		if (hasAlternateData)
542 		{
543 			sstreamAlternateExpected << m_test_data.m_alternate_expected_geometry[n] << ", ";
544 		}
545 		sstreamResult << result_geometry_ptr[n] << ", ";
546 
547 		if (matchesExpected && de::abs(result_geometry_ptr[n] - m_test_data.m_expected_geometry[n]) >= m_epsilon)
548 		{
549 			matchesExpected = false;
550 			differentIndex	= n;
551 		}
552 		if (matchesAlternateExpected &&
553 			de::abs(result_geometry_ptr[n] - m_test_data.m_alternate_expected_geometry[n]) >= m_epsilon)
554 		{
555 			matchesAlternateExpected = false;
556 			differentAlternateIndex	 = n;
557 		}
558 		if (!matchesExpected && !matchesAlternateExpected)
559 		{
560 			gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
561 
562 			m_testCtx.getLog()
563 				<< tcu::TestLog::Message << "At [" << differentIndex
564 				<< "] position geometry buffer position Reference value is different than the rendered data (epsilon "
565 				<< m_epsilon << " )"
566 				<< " (" << m_test_data.m_expected_geometry[differentIndex] << ") vs "
567 				<< "(" << result_geometry_ptr[differentIndex] << ")" << tcu::TestLog::EndMessage;
568 
569 			if (hasAlternateData)
570 			{
571 				m_testCtx.getLog()
572 					<< tcu::TestLog::Message << "At [" << differentAlternateIndex
573 					<< "] alternate position geometry buffer position Reference value is different than the rendered data (epsilon "
574 					<< m_epsilon << " )"
575 					<< " (" << m_test_data.m_alternate_expected_geometry[differentAlternateIndex] << ") vs "
576 					<< "(" << result_geometry_ptr[differentAlternateIndex] << ")" << tcu::TestLog::EndMessage;
577 			}
578 
579 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
580 			return STOP;
581 		}
582 	}
583 
584 	if (matchesExpected && !adjacentMatchesExpected)
585 	{
586 		m_testCtx.getLog() << tcu::TestLog::Message
587 						   << "Geometry matches OpenGL ordering but adjacent geometry matches Vulkan ordering"
588 						   << tcu::TestLog::EndMessage;
589 
590 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
591 		return STOP;
592 	}
593 	if (matchesAlternateExpected && !adjacentMatchesAlternateExpected)
594 	{
595 		m_testCtx.getLog() << tcu::TestLog::Message
596 						   << "Geometry matches Vulkan ordering but adjacent geometry matches OpenGL ordering"
597 						   << tcu::TestLog::EndMessage;
598 
599 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
600 		return STOP;
601 	}
602 
603 	sstreamExpected << "]";
604 	sstreamResult << "]";
605 	if (hasAlternateData)
606 	{
607 		sstreamAlternateExpected << "]";
608 
609 		sstreamExpected << "\nor\n" << sstreamAlternateExpected.str();
610 	}
611 	m_testCtx.getLog() << tcu::TestLog::Message << "Expected: " << sstreamExpected.str().c_str()
612 					   << tcu::TestLog::EndMessage;
613 	m_testCtx.getLog() << tcu::TestLog::Message << "Result:  " << sstreamResult.str().c_str()
614 					   << tcu::TestLog::EndMessage;
615 
616 	gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
617 
618 	m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
619 	return STOP;
620 }
621 
622 } // namespace glcts
623