1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2024 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 /**
25 */ /*!
26 * \file glcTransformFeedbackTests.cpp
27 * \brief Conformance tests for the transform_feedback2 functionality.
28 */ /*-------------------------------------------------------------------*/
29
30 #include "deMath.h"
31
32 #include "glcTransformFeedbackTests.hpp"
33 #include "gluDefs.hpp"
34 #include "gluShaderProgram.hpp"
35 #include "gluContextInfo.hpp"
36 #include "glwEnums.hpp"
37 #include "glwFunctions.hpp"
38 #include "tcuStringTemplate.hpp"
39 #include "tcuTestLog.hpp"
40
41 using namespace glw;
42 using namespace glu;
43
44 namespace
45 {
46 // clang-format off
47 GLfloat vertices[24] = {
48 -0.8f, -0.8f, 0.0f, 1.0f,
49 0.8f, -0.8f, 0.0f, 1.0f,
50 -0.8f, 0.8f, 0.0f, 1.0f,
51
52 0.8f, 0.8f, 0.0f, 1.0f,
53 -0.8f, 0.8f, 0.0f, 1.0f,
54 0.8f, -0.8f, 0.0f, 1.0f,
55 };
56 // clang-format on
57
58 } // namespace
59
60 namespace glcts
61 {
62
63 // clang-format off
64 /** @brief Vertex shader source code to test transform feedback states conformance. */
65 const glw::GLchar* glcts::TransformFeedbackStatesTestCase::m_shader_vert =
66 R"(${VERSION}
67 in vec4 in_vertex;
68
69 void main (void)
70 {
71 vec4 temp = in_vertex;
72
73 temp.xyz *= 0.5;
74
75 gl_Position = temp;
76 }
77 )";
78
79 /** @brief Fragment shader source code to test transform feedback states conformance. */
80 const glw::GLchar* glcts::TransformFeedbackStatesTestCase::m_shader_frag =
81 R"(${VERSION}
82 ${PRECISION}
83 out vec4 frag;
84 void main (void)
85 {
86 frag = vec4(0.0);
87 }
88 )";
89 // clang-format on
90
91 /** Constructor.
92 *
93 * @param context Rendering context
94 */
TransformFeedbackStatesTestCase(deqp::Context & context)95 TransformFeedbackStatesTestCase::TransformFeedbackStatesTestCase(deqp::Context &context)
96 : TestCase(context, "transform_feedback2_states", "Verifies transform feedback objects with different states")
97 , m_program(0)
98 , m_vao(0)
99 , m_buffers{0, 0}
100 , m_tf_id(0)
101 , m_queries{0, 0}
102 , m_isContextES(false)
103 , m_testSupported(false)
104 {
105 }
106
~TransformFeedbackStatesTestCase()107 TransformFeedbackStatesTestCase::~TransformFeedbackStatesTestCase()
108 {
109 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
110
111 gl.deleteQueries(2, m_queries);
112 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteQueries");
113
114 gl.deleteBuffers(2, m_buffers);
115 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteBuffers");
116
117 if (m_tf_id != 0)
118 {
119 gl.deleteTransformFeedbacks(1, &m_tf_id);
120 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteTransformFeedbacks");
121 }
122
123 if (m_vao != 0)
124 {
125 gl.deleteVertexArrays(1, &m_vao);
126 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteVertexArrays");
127 }
128
129 if (m_program != 0)
130 {
131 gl.deleteProgram(m_program);
132 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteProgram");
133 }
134 }
135
136 /** Stub deinit method. */
deinit()137 void TransformFeedbackStatesTestCase::deinit()
138 {
139 /* Left blank intentionally */
140 }
141
142 /** Stub init method */
init()143 void TransformFeedbackStatesTestCase::init()
144 {
145 const glu::RenderContext &renderContext = m_context.getRenderContext();
146 glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(renderContext.getType());
147 m_isContextES = glu::isContextTypeES(renderContext.getType());
148
149 specializationMap["VERSION"] = glu::getGLSLVersionDeclaration(glslVersion);
150 specializationMap["PRECISION"] = "";
151
152 if (m_isContextES)
153 {
154 specializationMap["PRECISION"] = "precision highp float;";
155 m_testSupported = true;
156 }
157 else
158 {
159 auto contextType = m_context.getRenderContext().getType();
160 m_testSupported = (glu::contextSupports(contextType, glu::ApiType::core(1, 4)) &&
161 m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2")) ||
162 glu::contextSupports(contextType, glu::ApiType::core(4, 0));
163 }
164 }
165
166 /* Compiles and links transform feedback program. */
buildTransformFeedbackProgram(const char * vsSource,const char * fsSource)167 void TransformFeedbackStatesTestCase::buildTransformFeedbackProgram(const char *vsSource, const char *fsSource)
168 {
169 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
170
171 GLint status = 0;
172 m_program = gl.createProgram();
173 if (!m_program)
174 {
175 TCU_FAIL("Program object not valid");
176 }
177 GLU_EXPECT_NO_ERROR(gl.getError(), "createProgram");
178
179 // vertex shader
180 {
181 GLuint vShader = gl.createShader(GL_VERTEX_SHADER);
182 if (!vShader)
183 {
184 TCU_FAIL("Shader object not valid");
185 }
186 GLU_EXPECT_NO_ERROR(gl.getError(), "createShader");
187
188 gl.shaderSource(vShader, 1, (const char **)&vsSource, NULL);
189 GLU_EXPECT_NO_ERROR(gl.getError(), "shaderSource");
190
191 gl.compileShader(vShader);
192 GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader");
193
194 gl.getShaderiv(vShader, GL_COMPILE_STATUS, &status);
195 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
196
197 if (status == GL_FALSE)
198 {
199 GLint infoLogLength = 0;
200 gl.getShaderiv(vShader, GL_INFO_LOG_LENGTH, &infoLogLength);
201 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
202
203 std::vector<char> infoLogBuf(infoLogLength + 1);
204 gl.getShaderInfoLog(vShader, (GLsizei)infoLogBuf.size(), NULL, infoLogBuf.data());
205 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderInfoLog");
206
207 m_testCtx.getLog() << tcu::TestLog::Message << "Vertex shader build failed.\n"
208 << "Vertex: " << infoLogBuf.data() << "\n"
209 << vsSource << "\n"
210 << tcu::TestLog::EndMessage;
211
212 gl.deleteShader(vShader);
213 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
214
215 TCU_FAIL("Failed to compile transform feedback vertex shader");
216 }
217 gl.attachShader(m_program, vShader);
218 GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
219
220 gl.deleteShader(vShader);
221 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
222 }
223
224 if (fsSource)
225 {
226 GLuint fShader = gl.createShader(GL_FRAGMENT_SHADER);
227 gl.shaderSource(fShader, 1, (const char **)&fsSource, NULL);
228 GLU_EXPECT_NO_ERROR(gl.getError(), "shaderSource");
229
230 gl.compileShader(fShader);
231 GLU_EXPECT_NO_ERROR(gl.getError(), "compileShader");
232
233 gl.getShaderiv(fShader, GL_COMPILE_STATUS, &status);
234 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
235
236 if (status == GL_FALSE)
237 {
238 GLint infoLogLength = 0;
239 gl.getShaderiv(fShader, GL_INFO_LOG_LENGTH, &infoLogLength);
240 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderiv");
241
242 std::vector<char> infoLogBuf(infoLogLength + 1);
243 gl.getShaderInfoLog(fShader, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]);
244 GLU_EXPECT_NO_ERROR(gl.getError(), "getShaderInfoLog");
245
246 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader build failed.\n"
247 << "Fragment: " << infoLogBuf.data() << "\n"
248 << fsSource << "\n"
249 << tcu::TestLog::EndMessage;
250
251 gl.deleteShader(fShader);
252 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
253
254 TCU_FAIL("Failed to compile transform feedback fragment shader");
255 }
256 gl.attachShader(m_program, fShader);
257 GLU_EXPECT_NO_ERROR(gl.getError(), "attachShader");
258
259 gl.deleteShader(fShader);
260 GLU_EXPECT_NO_ERROR(gl.getError(), "deleteShader");
261 }
262
263 const char *outputVaryings[] = {"gl_Position"};
264 int varyingcount = 1;
265
266 gl.transformFeedbackVaryings(m_program, varyingcount, &outputVaryings[0], GL_SEPARATE_ATTRIBS);
267 GLU_EXPECT_NO_ERROR(gl.getError(), "transformFeedbackVaryings");
268
269 gl.linkProgram(m_program);
270 GLU_EXPECT_NO_ERROR(gl.getError(), "linkProgram");
271
272 gl.getProgramiv(m_program, GL_LINK_STATUS, &status);
273 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
274
275 if (status == GL_FALSE)
276 {
277 GLint infoLogLength = 0;
278 gl.getProgramiv(m_program, GL_INFO_LOG_LENGTH, &infoLogLength);
279 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramiv");
280
281 std::vector<char> infoLogBuf(infoLogLength + 1);
282 gl.getProgramInfoLog(m_program, (GLsizei)infoLogBuf.size(), NULL, infoLogBuf.data());
283 GLU_EXPECT_NO_ERROR(gl.getError(), "getProgramInfoLog");
284
285 m_testCtx.getLog() << tcu::TestLog::Message << "Fragment shader build failed.\n"
286 << "link log: " << infoLogBuf.data() << "\n"
287 << tcu::TestLog::EndMessage;
288
289 TCU_FAIL("Failed to link transform feedback program");
290 }
291
292 gl.useProgram(m_program);
293 GLU_EXPECT_NO_ERROR(gl.getError(), "useProgram");
294 }
295
296 /** Executes test iteration.
297 *
298 * @return Returns STOP when test has finished executing, CONTINUE if more iterations are needed.
299 */
iterate()300 tcu::TestNode::IterateResult TransformFeedbackStatesTestCase::iterate()
301 {
302 if (!m_testSupported)
303 {
304 throw tcu::NotSupportedError("transform_feedback2 is not supported");
305 return STOP;
306 }
307
308 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
309 bool ret = true;
310
311 /* setup shader program */
312 std::string vshader = tcu::StringTemplate(m_shader_vert).specialize(specializationMap);
313 std::string fshader = tcu::StringTemplate(m_shader_frag).specialize(specializationMap);
314
315 {
316 ProgramSources sources;
317 sources.sources[SHADERTYPE_VERTEX].push_back(vshader);
318 sources.sources[SHADERTYPE_FRAGMENT].push_back(fshader);
319
320 ShaderProgram checker_program(gl, sources);
321
322 if (!checker_program.isOk())
323 {
324 m_testCtx.getLog() << tcu::TestLog::Message << "Shader build failed.\n"
325 << "Vertex: " << checker_program.getShaderInfo(SHADERTYPE_VERTEX).infoLog << "\n"
326 << checker_program.getShader(SHADERTYPE_VERTEX)->getSource() << "\n"
327 << "Fragment: " << checker_program.getShaderInfo(SHADERTYPE_FRAGMENT).infoLog << "\n"
328 << checker_program.getShader(SHADERTYPE_FRAGMENT)->getSource() << "\n"
329 << "Program: " << checker_program.getProgramInfo().infoLog << tcu::TestLog::EndMessage;
330 TCU_FAIL("Compile failed");
331 }
332 }
333
334 // fragment shader needed for GLES program linking
335 buildTransformFeedbackProgram(vshader.c_str(), m_isContextES ? fshader.c_str() : nullptr);
336
337 GLuint queryresults[2] = {0, 0};
338 GLint bbinding = 0;
339 GLint64 bsize = 0, bstart = 0;
340
341 /* Create and bind a user transform feedback object with
342 GenTransformFeedbacks and BindTransformFeedback and ensure the test
343 runs correctly. Delete the user transform buffer object.
344
345 * Create multiple user transform feedback objects and configure different
346 state in each object. The state tested should be the following:
347
348 TRANSFORM_FEEDBACK_BUFFER_BINDING
349 TRANSFORM_FEEDBACK_BUFFER_START
350 TRANSFORM_FEEDBACK_BUFFER_SIZE
351 */
352 gl.genTransformFeedbacks(1, &m_tf_id);
353 GLU_EXPECT_NO_ERROR(gl.getError(), "genTransformFeedbacks");
354
355 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_tf_id);
356 GLU_EXPECT_NO_ERROR(gl.getError(), "bindTransformFeedback");
357
358 gl.genBuffers(2, m_buffers);
359 GLU_EXPECT_NO_ERROR(gl.getError(), "genBuffers");
360
361 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffers[0]);
362 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
363
364 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), NULL, GL_STATIC_DRAW);
365 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
366
367 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffers[0]);
368 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBufferBase");
369
370 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffers[1]);
371 GLU_EXPECT_NO_ERROR(gl.getError(), "bindBuffer");
372
373 gl.bufferData(GL_ARRAY_BUFFER, sizeof(vertices), &vertices, GL_STATIC_DRAW);
374 GLU_EXPECT_NO_ERROR(gl.getError(), "bufferData");
375
376 /*Test*/
377 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, &bbinding);
378 GLU_EXPECT_NO_ERROR(gl.getError(), "getIntegerv");
379
380 if (m_isContextES)
381 {
382 gl.getInteger64i_v(GL_TRANSFORM_FEEDBACK_BUFFER_START, 0, &bstart);
383 GLU_EXPECT_NO_ERROR(gl.getError(), "getInteger64i_v");
384
385 gl.getInteger64i_v(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, 0, &bsize);
386 GLU_EXPECT_NO_ERROR(gl.getError(), "getInteger64i_v");
387 }
388 else
389 {
390 gl.getTransformFeedbacki64_v(m_tf_id, GL_TRANSFORM_FEEDBACK_BUFFER_START, 0, &bstart);
391 GLU_EXPECT_NO_ERROR(gl.getError(), "getTransformFeedbacki64_v");
392
393 gl.getTransformFeedbacki64_v(m_tf_id, GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, 0, &bsize);
394 GLU_EXPECT_NO_ERROR(gl.getError(), "getTransformFeedbacki64_v");
395 }
396
397 if (bbinding >= 0 && ((GLuint)bbinding != m_tf_id) && (bstart != 0) && (bsize != sizeof(vertices)))
398 {
399 TCU_FAIL("Unexpected state of transform feedback buffer");
400 }
401
402 /*
403 * Create two query objects and call BeginQuery(PRIMITIVES_GENERATED) and
404 BeginQuery(TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN), which can be used
405 to determine when feedback is complete.
406 */
407 gl.genQueries(2, m_queries);
408 GLU_EXPECT_NO_ERROR(gl.getError(), "genQueries");
409
410 if (!m_isContextES)
411 {
412 gl.beginQuery(GL_PRIMITIVES_GENERATED, m_queries[0]);
413 GLU_EXPECT_NO_ERROR(gl.getError(), "beginQuery");
414 }
415
416 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_queries[1]);
417 GLU_EXPECT_NO_ERROR(gl.getError(), "beginQuery");
418
419 ret = draw_simple2(m_program, GL_TRIANGLES, 6, true);
420 if (!ret)
421 {
422 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
423 return STOP;
424 }
425
426 if (!m_isContextES)
427 {
428 gl.endQuery(GL_PRIMITIVES_GENERATED);
429 GLU_EXPECT_NO_ERROR(gl.getError(), "endQuery");
430 }
431
432 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
433 GLU_EXPECT_NO_ERROR(gl.getError(), "endQuery");
434
435 if (!m_isContextES)
436 {
437 gl.getQueryObjectuiv(m_queries[0], GL_QUERY_RESULT, &queryresults[0]);
438 GLU_EXPECT_NO_ERROR(gl.getError(), "getQueryObjectuiv");
439 }
440
441 gl.getQueryObjectuiv(m_queries[1], GL_QUERY_RESULT, &queryresults[1]);
442 GLU_EXPECT_NO_ERROR(gl.getError(), "getQueryObjectuiv");
443
444 if ((!m_isContextES && queryresults[0] != 5) || queryresults[1] != 2)
445 {
446 ret = false;
447
448 if (!m_isContextES)
449 {
450 m_testCtx.getLog() << tcu::TestLog::Message << "Query result error: " << queryresults[0] << " != 5, "
451 << queryresults[1] << " != 2" << tcu::TestLog::EndMessage;
452 }
453 else
454 {
455 m_testCtx.getLog() << tcu::TestLog::Message << "Query result error: " << queryresults[1] << " != 2"
456 << tcu::TestLog::EndMessage;
457 }
458 }
459
460 if (ret)
461 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
462 else
463 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
464 return STOP;
465 }
466
467 /* basic drawing function
468 MH-2024.05.10: stripped while porting from kc (GTFTransformFeedback2.c; drawsimple2) to vk-gl due to limited use in one test */
draw_simple2(GLuint program,GLenum primitivetype,GLint vertexcount,bool pauseresume)469 bool TransformFeedbackStatesTestCase::draw_simple2(GLuint program, GLenum primitivetype, GLint vertexcount,
470 bool pauseresume)
471 {
472 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
473
474 GLint locVertices = gl.getAttribLocation(program, "in_vertex");
475 if (locVertices < 0)
476 {
477 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
478 return false;
479 }
480 GLU_EXPECT_NO_ERROR(gl.getError(), "getAttribLocation");
481
482 bool result = true;
483
484 if (!m_isContextES)
485 {
486 gl.genVertexArrays(1, &m_vao);
487 GLU_EXPECT_NO_ERROR(gl.getError(), "genVertexArrays");
488 gl.bindVertexArray(m_vao);
489 GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
490 }
491
492 gl.clearColor(0.1f, 0.0f, 0.0f, 1.0f);
493 GLU_EXPECT_NO_ERROR(gl.getError(), "clearColor");
494 gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
495 GLU_EXPECT_NO_ERROR(gl.getError(), "clear");
496
497 gl.vertexAttribPointer(locVertices, 4, GL_FLOAT, GL_FALSE, 0, NULL);
498 GLU_EXPECT_NO_ERROR(gl.getError(), "vertexAttribPointer");
499 gl.enableVertexAttribArray(locVertices);
500 GLU_EXPECT_NO_ERROR(gl.getError(), "enableVertexAttribArray");
501
502 gl.beginTransformFeedback(primitivetype);
503 GLU_EXPECT_NO_ERROR(gl.getError(), "beginTransformFeedback");
504
505 if (pauseresume)
506 {
507 /* Query the transform feedback state for TRANSFORM_FEEDBACK_BUFFER_PAUSED
508 and TRANSFORM_FEEDBACK_BUFFER_ACTIVE to verify the state is reflected
509 correctly.
510 */
511 GLboolean paused, active;
512
513 gl.pauseTransformFeedback();
514 GLU_EXPECT_NO_ERROR(gl.getError(), "pauseTransformFeedback");
515
516 /* While the transform feedback is paused, verify that drawing with
517 incompatible primitives does not produce an error like it would when
518 transform feedback is not paused.
519 */
520 gl.drawArrays(GL_LINES, 0, vertexcount);
521 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
522
523 if (gl.getError() != GL_NO_ERROR)
524 {
525 result = false;
526 }
527
528 gl.getBooleanv(GL_TRANSFORM_FEEDBACK_PAUSED, &paused);
529 GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
530
531 gl.getBooleanv(GL_TRANSFORM_FEEDBACK_ACTIVE, &active);
532 GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
533
534 if (!paused || !active)
535 {
536 result = false;
537 }
538
539 gl.resumeTransformFeedback();
540 GLU_EXPECT_NO_ERROR(gl.getError(), "resumeTransformFeedback");
541
542 gl.getBooleanv(GL_TRANSFORM_FEEDBACK_PAUSED, &paused);
543 GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
544
545 gl.getBooleanv(GL_TRANSFORM_FEEDBACK_ACTIVE, &active);
546 GLU_EXPECT_NO_ERROR(gl.getError(), "getBooleanv");
547
548 if (paused || !active)
549 {
550 result = false;
551 }
552 }
553
554 {
555 /* Draw primitives. For Halti only DrawArrays can be used with transform
556 feedback; it does not support DrawElements with transform feedback. In
557 addition Halti only supports independent primitives (POINTS, LINES and
558 TRIANGLES), no primitive restart interaction and no writing of
559 gl_Position.
560 */
561 gl.drawArrays(primitivetype, 0, vertexcount);
562 GLU_EXPECT_NO_ERROR(gl.getError(), "drawArrays");
563
564 if (!m_isContextES)
565 {
566 /* For Halti an overflow while writing out to transform feedback buffers
567 generates and GL_INVALID_OPERATION error. Clear out the error
568 in case of an overflow.
569 */
570 gl.getError();
571 }
572 }
573
574 gl.endTransformFeedback();
575 GLU_EXPECT_NO_ERROR(gl.getError(), "endTransformFeedback");
576
577 gl.disableVertexAttribArray(locVertices);
578 GLU_EXPECT_NO_ERROR(gl.getError(), "disableVertexAttribArray");
579
580 if (!m_isContextES)
581 {
582 gl.bindVertexArray(0);
583 GLU_EXPECT_NO_ERROR(gl.getError(), "bindVertexArray");
584 }
585 return result;
586 }
587
588 /** Constructor.
589 *
590 * @param context Rendering context.
591 */
TransformFeedbackTests(deqp::Context & context)592 TransformFeedbackTests::TransformFeedbackTests(deqp::Context &context)
593 : TestCaseGroup(context, "transform_feedback2", "Verify conformance of transform_feedback2 functionality")
594 {
595 }
596
597 /** Initializes the test group contents. */
init()598 void TransformFeedbackTests::init()
599 {
600 addChild(new TransformFeedbackStatesTestCase(m_context));
601 }
602
603 } // namespace glcts
604