1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-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 /**
25 */ /*!
26 * \file gl3cTransformFeedback.cpp
27 * \brief Transform Feedback Test Suite Implementation
28 */ /*-------------------------------------------------------------------*/
29
30 /* Includes. */
31 #include "gl3cTransformFeedbackTests.hpp"
32 #include "gluContextInfo.hpp"
33 #include "gluDefs.hpp"
34 #include "gluRenderContext.hpp"
35 #include "gluStrUtil.hpp"
36 #include "tcuTestLog.hpp"
37
38 #include <algorithm>
39 #include <climits>
40 #include <cmath>
41 #include <cstdlib>
42 #include <sstream>
43
44 /* Stringify macro. */
45 #define _STR(s) STR(s)
46 #define STR(s) #s
47
48 /* Unused attribute / variable MACRO.
49 Some methods of clesses' heirs do not need all function parameters.
50 This triggers warnings on GCC platform. This macro will silence them.
51 */
52 #ifdef __GNUC__
53 #define UNUSED __attribute__((__unused__))
54 #else
55 #define UNUSED
56 #endif
57
Tests(deqp::Context & context)58 gl3cts::TransformFeedback::Tests::Tests(deqp::Context& context)
59 : TestCaseGroup(context, "transform_feedback", "Transform Feedback Test Suite")
60 {
61 addChild(new TransformFeedback::APIErrors(m_context));
62 addChild(new TransformFeedback::LinkingErrors(m_context));
63 addChild(new TransformFeedback::Limits(m_context));
64 addChild(new TransformFeedback::CaptureVertexInterleaved(m_context, "capture_vertex_interleaved_test",
65 "Transform Feedback Capture Vertex Interleaved Test"));
66 addChild(new TransformFeedback::CaptureGeometryInterleaved(m_context, "capture_geometry_interleaved_test",
67 "Transform Feedback Capture Geometry Interleaved Test"));
68 addChild(new TransformFeedback::CaptureVertexSeparate(m_context, "capture_vertex_separate_test",
69 "Transform Feedback Capture Vertex Separate Test"));
70 addChild(new TransformFeedback::CaptureGeometrySeparate(m_context, "capture_geometry_separate_test",
71 "Transform Feedback Capture Geometry Separate Test"));
72 addChild(new TransformFeedback::CheckGetXFBVarying(m_context, "get_xfb_varying",
73 "Transform Feedback Varying Getters Test"));
74 addChild(new TransformFeedback::QueryVertexInterleaved(m_context, "query_vertex_interleaved_test",
75 "Transform Feedback Query Vertex Interleaved Test"));
76 addChild(new TransformFeedback::QueryGeometryInterleaved(m_context, "query_geometry_interleaved_test",
77 "Transform Feedback Query Geometry Interleaved Test"));
78 addChild(new TransformFeedback::QueryVertexSeparate(m_context, "query_vertex_separate_test",
79 "Transform Feedback Query Vertex Separate Test"));
80 addChild(new TransformFeedback::QueryGeometrySeparate(m_context, "query_geometry_separate_test",
81 "Transform Feedback Query Geometry Separate Test"));
82 addChild(new TransformFeedback::DiscardVertex(m_context, "discard_vertex_test",
83 "Transform Feedback Discard Vertex Test"));
84 addChild(new TransformFeedback::DiscardGeometry(m_context, "discard_geometry_test",
85 "Transform Feedback Discard Geometry Test"));
86 addChild(new TransformFeedback::DrawXFB(m_context, "draw_xfb_test", "Transform Feedback Draw Test"));
87 addChild(new TransformFeedback::DrawXFBFeedback(m_context, "draw_xfb_feedbackk_test",
88 "Transform Feedback Draw Feedback Test"));
89 addChild(
90 new TransformFeedback::DrawXFBStream(m_context, "draw_xfb_stream_test", "Transform Feedback Draw Stream Test"));
91 addChild(new TransformFeedback::CaptureSpecialInterleaved(m_context, "capture_special_interleaved_test",
92 "Transform Feedback Capture Special Test"));
93 addChild(new TransformFeedback::DrawXFBInstanced(m_context, "draw_xfb_instanced_test",
94 "Transform Feedback Draw Instanced Test"));
95 addChild(new TransformFeedback::DrawXFBStreamInstanced(m_context, "draw_xfb_stream_instanced_test",
96 "Transform Feedback Draw Stream Instanced Test"));
97 }
98
~Tests(void)99 gl3cts::TransformFeedback::Tests::~Tests(void)
100 {
101 }
102
init(void)103 void gl3cts::TransformFeedback::Tests::init(void)
104 {
105 }
106
APIErrors(deqp::Context & context)107 gl3cts::TransformFeedback::APIErrors::APIErrors(deqp::Context& context)
108 : deqp::TestCase(context, "api_errors_test", "Transform Feedback API Errors Test")
109 , m_context(context)
110 , m_buffer_0(0)
111 , m_buffer_1(0)
112 , m_vertex_array_object(0)
113 , m_transform_feedback_object_0(0)
114 , m_transform_feedback_object_1(0)
115 , m_query_object(0)
116 , m_program_id_with_input_output(0)
117 , m_program_id_with_output(0)
118 , m_program_id_without_output(0)
119 , m_program_id_with_geometry_shader(0)
120 , m_program_id_with_tessellation_shaders(0)
121 , m_glBindBufferOffsetEXT(DE_NULL)
122 , m_glGetIntegerIndexedvEXT(DE_NULL)
123 , m_glGetBooleanIndexedvEXT(DE_NULL)
124 {
125 }
126
~APIErrors(void)127 gl3cts::TransformFeedback::APIErrors::~APIErrors(void)
128 {
129 }
130
iterate(void)131 tcu::TestNode::IterateResult gl3cts::TransformFeedback::APIErrors::iterate(void)
132 {
133 /* Functions handler */
134 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
135
136 /* Initializations. */
137 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
138 bool is_at_least_gl_33 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 3)));
139 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
140 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
141
142 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
143 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
144 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
145 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
146
147 if (is_ext_tf_1)
148 {
149 /* Extension query. */
150 m_glBindBufferOffsetEXT =
151 (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT");
152 m_glGetIntegerIndexedvEXT =
153 (GetIntegerIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetIntegerIndexedvEXT");
154 m_glGetBooleanIndexedvEXT =
155 (GetBooleanIndexedvEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glGetBooleanIndexedvEXT");
156 }
157
158 if (is_at_least_gl_40 || is_arb_tf_2)
159 {
160 /* Create transform feedback objects. */
161 gl.genTransformFeedbacks(1, &m_transform_feedback_object_0);
162
163 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
164 }
165
166 if (is_at_least_gl_40 || is_arb_tf_3)
167 {
168 /* Create query object. */
169 gl.genQueries(1, &m_query_object);
170
171 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
172 }
173
174 if (is_at_least_gl_42 || is_arb_tf_instanced)
175 {
176 /* Create transform feedback objects. */
177 gl.genTransformFeedbacks(1, &m_transform_feedback_object_1);
178
179 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
180 }
181
182 /* Default result. */
183 bool is_ok = true;
184 bool test_error = false;
185
186 /* Entities setup. */
187 try
188 {
189 /* VAO setup. */
190 gl.genVertexArrays(1, &m_vertex_array_object);
191 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
192
193 gl.bindVertexArray(m_vertex_array_object);
194 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
195
196 /* Buffer setup. */
197 gl.genBuffers(1, &m_buffer_0);
198 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
199
200 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_0);
201 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
202
203 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, 16, NULL, GL_STATIC_DRAW);
204 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
205
206 gl.genBuffers(1, &m_buffer_1);
207 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
208
209 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer_1);
210 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
211
212 gl.bufferData(GL_ARRAY_BUFFER, m_buffer_1_size, m_buffer_1_data, GL_STATIC_DRAW);
213 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
214
215 /* Programs setup. */
216
217 m_program_id_with_input_output = gl3cts::TransformFeedback::Utilities::buildProgram(
218 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_input_output,
219 s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS);
220
221 m_program_id_with_output = gl3cts::TransformFeedback::Utilities::buildProgram(
222 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_with_output, s_fragment_shader,
223 &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS, true);
224
225 m_program_id_without_output = gl3cts::TransformFeedback::Utilities::buildProgram(
226 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_without_output,
227 s_fragment_shader, NULL, 0, GL_SEPARATE_ATTRIBS);
228
229 is_ok = is_ok && m_program_id_with_input_output && m_program_id_with_output && m_program_id_without_output;
230
231 if (is_at_least_gl_33) {
232 m_program_id_with_geometry_shader = gl3cts::TransformFeedback::Utilities::buildProgram(
233 gl, m_context.getTestContext().getLog(), m_geometry_shader, NULL, NULL, s_vertex_shader_without_output,
234 s_fragment_shader, &m_varying_name, 1, GL_INTERLEAVED_ATTRIBS);
235
236 is_ok = is_ok && m_program_id_with_geometry_shader;
237 }
238
239 if (is_at_least_gl_40) {
240 m_program_id_with_tessellation_shaders = gl3cts::TransformFeedback::Utilities::buildProgram(
241 gl, m_context.getTestContext().getLog(), NULL, m_tessellation_control_shader,
242 m_tessellation_evaluation_shader, s_vertex_shader_without_output, s_fragment_shader, &m_varying_name, 1,
243 GL_INTERLEAVED_ATTRIBS);
244 is_ok = is_ok && m_program_id_with_tessellation_shaders;
245 }
246 }
247 catch (...)
248 {
249 is_ok = false;
250 test_error = true;
251 }
252
253 /* Iterating tests. */
254 try
255 {
256 if (is_at_least_gl_30 || is_ext_tf_1)
257 {
258 is_ok = is_ok && testExtension1();
259 }
260
261 if (is_at_least_gl_40 || is_arb_tf_2)
262 {
263 is_ok = is_ok && testExtension2();
264 }
265
266 if (is_at_least_gl_40 || is_arb_tf_3)
267 {
268 is_ok = is_ok && testExtension3();
269 }
270
271 if (is_at_least_gl_42 || is_arb_tf_instanced)
272 {
273 is_ok = is_ok && testInstanced();
274 }
275 }
276 catch (...)
277 {
278 is_ok = false;
279 test_error = true;
280 }
281
282 /* Deinitialization. */
283 if (m_vertex_array_object)
284 {
285 gl.deleteVertexArrays(1, &m_vertex_array_object);
286
287 m_vertex_array_object = 0;
288 }
289
290 if (m_buffer_0)
291 {
292 gl.deleteBuffers(1, &m_buffer_0); // silently unbinds
293
294 m_buffer_0 = 0;
295 }
296
297 if (m_buffer_1)
298 {
299 gl.deleteBuffers(1, &m_buffer_1); // silently unbinds
300
301 m_buffer_1 = 0;
302 }
303
304 if (m_transform_feedback_object_0)
305 {
306 gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0);
307
308 m_transform_feedback_object_0 = 0;
309 }
310
311 if (m_transform_feedback_object_1)
312 {
313 gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_1);
314
315 m_transform_feedback_object_1 = 0;
316 }
317
318 if (m_query_object)
319 {
320 gl.deleteQueries(1, &m_query_object);
321
322 m_query_object = 0;
323 }
324
325 if (m_program_id_with_input_output)
326 {
327 gl.deleteProgram(m_program_id_with_input_output);
328
329 m_program_id_with_input_output = 0;
330 }
331
332 if (m_program_id_with_output)
333 {
334 gl.deleteProgram(m_program_id_with_output);
335
336 m_program_id_with_output = 0;
337 }
338
339 if (m_program_id_without_output)
340 {
341 gl.deleteProgram(m_program_id_without_output);
342
343 m_program_id_without_output = 0;
344 }
345
346 if (m_program_id_with_geometry_shader)
347 {
348 gl.deleteProgram(m_program_id_with_geometry_shader);
349
350 m_program_id_with_geometry_shader = 0;
351 }
352
353 if (m_program_id_with_tessellation_shaders)
354 {
355 gl.deleteProgram(m_program_id_with_tessellation_shaders);
356
357 m_program_id_with_tessellation_shaders = 0;
358 }
359
360 /* Result's setup. */
361 if (is_ok)
362 {
363 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
364 }
365 else
366 {
367 if (test_error)
368 {
369 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
370 }
371 else
372 {
373 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
374 }
375 }
376
377 return STOP;
378 }
379
testExtension1(void)380 bool gl3cts::TransformFeedback::APIErrors::testExtension1(void)
381 {
382 /* Functions handler */
383 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
384
385 /* INVALID_VALUE is generated by BindBufferRange, BindBufferOffset and
386 BindBufferBase when <index> is greater or equal to
387 MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS; */
388
389 glw::GLint index_count = 0;
390
391 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &index_count);
392
393 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
394
395 if (index_count == 0)
396 {
397 m_context.getTestContext().getLog() << tcu::TestLog::Message << "glGetIntegerv did not returned any value."
398 << tcu::TestLog::EndMessage;
399 throw 0;
400 }
401
402 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 16);
403
404 if (GL_INVALID_VALUE != gl.getError())
405 {
406 m_context.getTestContext().getLog() << tcu::TestLog::Message
407 << "INVALID_VALUE was not generated by BindBufferRange "
408 "when <index> was greater or equal to "
409 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
410 << tcu::TestLog::EndMessage;
411 return false;
412 }
413
414 if (DE_NULL != m_glBindBufferOffsetEXT)
415 {
416 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0);
417
418 if (GL_INVALID_VALUE != gl.getError())
419 {
420 m_context.getTestContext().getLog() << tcu::TestLog::Message
421 << "INVALID_VALUE was not generated by BindBufferOffset "
422 "when <index> was greater or equal to "
423 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
424 << tcu::TestLog::EndMessage;
425 return false;
426 }
427 }
428
429 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0);
430
431 if (GL_INVALID_VALUE != gl.getError())
432 {
433 m_context.getTestContext().getLog() << tcu::TestLog::Message
434 << "INVALID_VALUE was not generated by "
435 "BindBufferBase when <index> was greater or equal to "
436 "MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS."
437 << tcu::TestLog::EndMessage;
438 return false;
439 }
440
441 /* INVALID_VALUE is generated by BindBufferRange when <size> is less or equal to zero; */
442
443 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 0);
444
445 if (GL_INVALID_VALUE != gl.getError())
446 {
447 m_context.getTestContext().getLog()
448 << tcu::TestLog::Message
449 << "INVALID_VALUE was not generated by BindBufferRange when <size> was less or equal to zero."
450 << tcu::TestLog::EndMessage;
451 return false;
452 }
453
454 /* INVALID_VALUE is generated by BindBufferRange and BindBufferOffset
455 when <offset> is not word-aligned; */
456
457 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3, 4);
458
459 if (GL_INVALID_VALUE != gl.getError())
460 {
461 m_context.getTestContext().getLog()
462 << tcu::TestLog::Message
463 << "INVALID_VALUE was not generated by BindBufferRange when <offset> was not word-aligned."
464 << tcu::TestLog::EndMessage;
465 return false;
466 }
467
468 if (DE_NULL != m_glBindBufferOffsetEXT)
469 {
470 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 3);
471
472 if (GL_INVALID_VALUE != gl.getError())
473 {
474 m_context.getTestContext().getLog()
475 << tcu::TestLog::Message
476 << "INVALID_VALUE was not generated by BindBufferOffset when <offset> was not word-aligned."
477 << tcu::TestLog::EndMessage;
478 return false;
479 }
480 }
481
482 /* INVALID_VALUE is generated by BindBufferRange when <size> is not word-aligned; */
483
484 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, index_count, m_buffer_0, 0, 3);
485
486 if (GL_INVALID_VALUE != gl.getError())
487 {
488 m_context.getTestContext().getLog()
489 << tcu::TestLog::Message
490 << "INVALID_VALUE was not generated by BindBufferRange when <size> was not word-aligned."
491 << tcu::TestLog::EndMessage;
492 return false;
493 }
494
495 /* INVALID_OPERATION is generated by BindBufferRange, BindBufferOffset and
496 BindBufferBase when <target> is TRANSFORM_FEEDBACK_BUFFER and transform
497 feedback is active; */
498
499 gl.useProgram(m_program_id_with_output);
500
501 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
502
503 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
504
505 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
506
507 gl.beginTransformFeedback(GL_POINTS);
508
509 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
510
511 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0, 16);
512
513 if (GL_INVALID_OPERATION != gl.getError())
514 {
515 m_context.getTestContext().getLog() << tcu::TestLog::Message
516 << "INVALID_OPERATION was not generated by BindBufferRange "
517 "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
518 "feedback was active."
519 << tcu::TestLog::EndMessage;
520
521 gl.endTransformFeedback();
522
523 return false;
524 }
525
526 if (DE_NULL != m_glBindBufferOffsetEXT)
527 {
528 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0, 0);
529
530 if (GL_INVALID_OPERATION != gl.getError())
531 {
532 m_context.getTestContext().getLog() << tcu::TestLog::Message
533 << "INVALID_OPERATION was not generated by BindBufferOffset "
534 "when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
535 "feedback was active."
536 << tcu::TestLog::EndMessage;
537
538 gl.endTransformFeedback();
539
540 return false;
541 }
542 }
543
544 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
545
546 if (GL_INVALID_OPERATION != gl.getError())
547 {
548 m_context.getTestContext().getLog()
549 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by "
550 "BindBufferBase when <target> was TRANSFORM_FEEDBACK_BUFFER and transform "
551 "feedback was active."
552 << tcu::TestLog::EndMessage;
553
554 gl.endTransformFeedback();
555
556 return false;
557 }
558
559 gl.endTransformFeedback();
560
561 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
562
563 /* INVALID_OPERATION is generated by UseProgram when transform feedback is
564 active; */
565
566 gl.beginTransformFeedback(GL_POINTS);
567
568 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
569
570 gl.useProgram(0);
571
572 if (GL_INVALID_OPERATION != gl.getError())
573 {
574 m_context.getTestContext().getLog()
575 << tcu::TestLog::Message
576 << "INVALID_OPERATION was not generated by UseProgram when transform feedback was active."
577 << tcu::TestLog::EndMessage;
578
579 gl.endTransformFeedback();
580
581 return false;
582 }
583
584 gl.endTransformFeedback();
585
586 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
587
588 /* INVALID_OPERATION is generated by LinkProgram when <program> is currently
589 active and transform feedback is active; */
590
591 gl.useProgram(m_program_id_with_output);
592
593 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
594
595 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
596
597 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
598
599 gl.beginTransformFeedback(GL_POINTS);
600
601 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
602
603 gl.linkProgram(m_program_id_with_output);
604
605 if (GL_INVALID_OPERATION != gl.getError())
606 {
607 m_context.getTestContext().getLog() << tcu::TestLog::Message
608 << "INVALID_OPERATION was not generated by LinkProgram when <program> was "
609 "currently active and transform feedback was active."
610 << tcu::TestLog::EndMessage;
611
612 gl.endTransformFeedback();
613
614 return false;
615 }
616
617 gl.endTransformFeedback();
618
619 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
620
621 /* INVALID_OPERATION is generated by BeginTransformFeedback when transform
622 feedback is active; */
623
624 gl.useProgram(m_program_id_with_output);
625
626 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
627
628 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
629
630 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
631
632 gl.beginTransformFeedback(GL_POINTS);
633
634 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
635
636 gl.beginTransformFeedback(GL_POINTS);
637
638 if (GL_INVALID_OPERATION != gl.getError())
639 {
640 m_context.getTestContext().getLog()
641 << tcu::TestLog::Message
642 << "INVALID_OPERATION was not generated by BeginTransformFeedback when transform feedback was active."
643 << tcu::TestLog::EndMessage;
644
645 gl.endTransformFeedback();
646
647 return false;
648 }
649
650 gl.endTransformFeedback();
651
652 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
653
654 /* INVALID_OPERATION is generated by EndTransformFeedback when transform
655 feedback is inactive; */
656
657 gl.endTransformFeedback();
658
659 if (GL_INVALID_OPERATION != gl.getError())
660 {
661 m_context.getTestContext().getLog()
662 << tcu::TestLog::Message
663 << "INVALID_OPERATION was not generated by EndTransformFeedback when transform feedback was inactive."
664 << tcu::TestLog::EndMessage;
665
666 return false;
667 }
668
669 /* INVALID_OPERATION is generated by draw command when generated primitives
670 type does not match <primitiveMode>; */
671
672 gl.useProgram(m_program_id_with_output);
673
674 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
675
676 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
677
678 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
679
680 gl.beginTransformFeedback(GL_POINTS);
681
682 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
683
684 gl.drawArrays(GL_LINES, 0, 2);
685
686 if (GL_INVALID_OPERATION != gl.getError())
687 {
688 m_context.getTestContext().getLog() << tcu::TestLog::Message
689 << "INVALID_OPERATION was not generated by draw command when generated "
690 "primitives type does not match <primitiveMode>."
691 << tcu::TestLog::EndMessage;
692
693 gl.endTransformFeedback();
694
695 return false;
696 }
697
698 gl.endTransformFeedback();
699
700 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
701
702 /* INVALID_OPERATION is generated by BeginTransformFeedback when any binding
703 point used by XFB does not have buffer bound; */
704
705 gl.useProgram(m_program_id_with_output);
706
707 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
708
709 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, 0);
710
711 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
712
713 gl.beginTransformFeedback(GL_POINTS);
714
715 if (GL_INVALID_OPERATION != gl.getError())
716 {
717 m_context.getTestContext().getLog() << tcu::TestLog::Message
718 << "INVALID_OPERATION was not generated by BeginTransformFeedback when any "
719 "binding point used by XFB does not have buffer bound."
720 << tcu::TestLog::EndMessage;
721
722 return false;
723 }
724
725 /* INVALID_OPERATION is generated by BeginTransformFeedback when no program
726 is active; */
727
728 gl.useProgram(0);
729
730 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
731
732 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
733
734 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
735
736 gl.beginTransformFeedback(GL_POINTS);
737
738 if (GL_INVALID_OPERATION != gl.getError())
739 {
740 m_context.getTestContext().getLog()
741 << tcu::TestLog::Message
742 << "INVALID_OPERATION was not generated by BeginTransformFeedback when no program was active."
743 << tcu::TestLog::EndMessage;
744
745 gl.endTransformFeedback();
746
747 return false;
748 }
749
750 /* INVALID_OPERATION is generated by BeginTransformFeedback when no variable
751 are specified to be captured in the active program; */
752
753 gl.useProgram(m_program_id_without_output);
754
755 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
756
757 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
758
759 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
760
761 gl.beginTransformFeedback(GL_POINTS);
762
763 if (GL_INVALID_OPERATION != gl.getError())
764 {
765 m_context.getTestContext().getLog()
766 << tcu::TestLog::Message
767 << "INVALID_OPERATION was not generated by BeginTransformFeedback when no variable "
768 "are specified to be captured in the active program."
769 << tcu::TestLog::EndMessage;
770
771 gl.endTransformFeedback();
772
773 return false;
774 }
775
776 /* INVALID_VALUE is generated by TransformFeedbackVaryings when <program> is
777 not id of the program object; */
778
779 unsigned short int invalid_name = 1;
780
781 while (gl.isProgram(invalid_name) || gl.isShader(invalid_name))
782 {
783 ++invalid_name;
784
785 /* Make sure that this loop ends someday, bad day. */
786 if (invalid_name == USHRT_MAX)
787 {
788 m_context.getTestContext().getLog()
789 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
790 throw 0;
791 }
792 }
793
794 gl.transformFeedbackVaryings((glw::GLuint)invalid_name, 1, &m_varying_name, GL_INTERLEAVED_ATTRIBS);
795
796 if (GL_INVALID_VALUE != gl.getError())
797 {
798 m_context.getTestContext().getLog() << tcu::TestLog::Message
799 << "INVALID_VALUE was not generated by TransformFeedbackVaryings when "
800 "<program> was not id of the program object."
801 << tcu::TestLog::EndMessage;
802 return false;
803 }
804
805 /* INVALID_VALUE is generated by TransformFeedbackVaryings when <bufferMode>
806 is SEPARATE_ATTRIBS and <count> is exceeds limits; */
807
808 glw::GLint max_separate_attribs = 0;
809
810 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_separate_attribs);
811
812 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
813
814 if (max_separate_attribs == 0)
815 {
816 m_context.getTestContext().getLog()
817 << tcu::TestLog::Message << "INVALID_VALUE was not generated by TransformFeedbackVaryings when <bufferMode>"
818 " was SEPARATE_ATTRIBS and <count> was exceeds limits."
819 << tcu::TestLog::EndMessage;
820 throw 0;
821 }
822
823 glw::GLint more_than_max_separate_attribs = max_separate_attribs + 1;
824
825 glw::GLchar** attrib = new glw::GLchar*[more_than_max_separate_attribs];
826
827 for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i)
828 {
829 std::string new_attrib = "a" + gl3cts::TransformFeedback::Utilities::itoa(i);
830
831 size_t new_attrib_size = new_attrib.size();
832
833 attrib[i] = new glw::GLchar[new_attrib_size + 1];
834
835 memset(attrib[i], 0, new_attrib_size + 1);
836
837 memcpy(attrib[i], new_attrib.c_str(), new_attrib_size);
838 }
839
840 gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_separate_attribs, attrib, GL_SEPARATE_ATTRIBS);
841
842 for (glw::GLint i = 0; i < more_than_max_separate_attribs; ++i)
843 {
844 delete[] attrib[i];
845 }
846
847 delete[] attrib;
848
849 if (GL_INVALID_VALUE != gl.getError())
850 {
851 m_context.getTestContext().getLog() << tcu::TestLog::Message
852 << "INVALID_VALUE was not generated by TransformFeedbackVaryings when "
853 "<bufferMode> was SEPARATE_ATTRIBS and <count> exceeded limits."
854 << tcu::TestLog::EndMessage;
855 return false;
856 }
857
858 /* INVALID_VALUE is generated by GetTransformFeedbackVarying when <index> is
859 greater than or equal to TRANSFORM_FEEDBACK_VARYINGS; */
860
861 glw::GLint transform_feedback_varyings = 0;
862
863 gl.getProgramiv(m_program_id_with_output, GL_TRANSFORM_FEEDBACK_VARYINGS, &transform_feedback_varyings);
864
865 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
866
867 if (transform_feedback_varyings == 0)
868 {
869 m_context.getTestContext().getLog() << tcu::TestLog::Message
870 << "glGetProgramiv failed to return GL_TRANSFORM_FEEDBACK_VARYINGS."
871 << tcu::TestLog::EndMessage;
872 throw 0;
873 }
874
875 glw::GLchar tmp_buffer[256];
876
877 glw::GLsizei tmp_size = 0;
878
879 glw::GLenum tmp_type = GL_NONE;
880
881 gl.getTransformFeedbackVarying(m_program_id_with_output, transform_feedback_varyings, sizeof(tmp_buffer), NULL,
882 &tmp_size, &tmp_type, tmp_buffer);
883
884 if (GL_INVALID_VALUE != gl.getError())
885 {
886 m_context.getTestContext().getLog() << tcu::TestLog::Message
887 << "INVALID_VALUE was not generated by GetTransformFeedbackVarying when "
888 "<index> was greater than or equal to TRANSFORM_FEEDBACK_VARYINGS."
889 << tcu::TestLog::EndMessage;
890 return false;
891 }
892
893 /* INVALID_VALUE is generated by GetIntegerIndexdv when <index> exceeds the
894 limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is one of the
895 following:
896 * TRANSFORM_FEEDBACK_BUFFER_BINDING,
897 * TRANSFORM_FEEDBACK_BUFFER_START,
898 * TRANSFORM_FEEDBACK_BUFFER_SIZE; */
899
900 if (DE_NULL != m_glGetIntegerIndexedvEXT)
901 {
902 glw::GLint tmp_int_value;
903
904 m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs, &tmp_int_value);
905
906 if (GL_INVALID_VALUE != gl.getError())
907 {
908 m_context.getTestContext().getLog()
909 << tcu::TestLog::Message
910 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
911 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
912 "TRANSFORM_FEEDBACK_BUFFER_BINDING."
913 << tcu::TestLog::EndMessage;
914 return false;
915 }
916
917 m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_START, more_than_max_separate_attribs, &tmp_int_value);
918
919 if (GL_INVALID_VALUE != gl.getError())
920 {
921 m_context.getTestContext().getLog()
922 << tcu::TestLog::Message
923 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
924 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
925 "GL_TRANSFORM_FEEDBACK_BUFFER_START."
926 << tcu::TestLog::EndMessage;
927 return false;
928 }
929
930 m_glGetIntegerIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, more_than_max_separate_attribs, &tmp_int_value);
931
932 if (GL_INVALID_VALUE != gl.getError())
933 {
934 m_context.getTestContext().getLog()
935 << tcu::TestLog::Message
936 << "INVALID_VALUE was not generated by GetIntegerIndexdv when <index> exceeds the "
937 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
938 "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE."
939 << tcu::TestLog::EndMessage;
940 return false;
941 }
942 }
943
944 /* INVALID_VALUE is generated by GetBooleanIndexedv when <index> exceeds the
945 limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> is
946 TRANSFORM_FEEDBACK_BUFFER_BINDING. */
947
948 if (DE_NULL != m_glGetBooleanIndexedvEXT)
949 {
950 glw::GLboolean tmp_bool_value;
951
952 m_glGetBooleanIndexedvEXT(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, more_than_max_separate_attribs,
953 &tmp_bool_value);
954
955 if (GL_INVALID_VALUE != gl.getError())
956 {
957 m_context.getTestContext().getLog()
958 << tcu::TestLog::Message
959 << "INVALID_VALUE was not generated by GetBooleanIndexedv when <index> exceeds the "
960 "limits of MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS and <param> was "
961 "TRANSFORM_FEEDBACK_BUFFER_BINDING."
962 << tcu::TestLog::EndMessage;
963 return false;
964 }
965 }
966
967 return true;
968 }
969
testExtension2(void)970 bool gl3cts::TransformFeedback::APIErrors::testExtension2(void)
971 {
972 /* Functions handler */
973 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
974
975 /* Bind Transform Feedback Object */
976 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
977
978 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
979
980 /* INVALID_OPERATION is generated by PauseTransformFeedback if current
981 transform feedback is not active or paused; */
982
983 gl.pauseTransformFeedback();
984
985 if (GL_INVALID_OPERATION != gl.getError())
986 {
987 m_context.getTestContext().getLog() << tcu::TestLog::Message
988 << "INVALID_OPERATION is not generated by PauseTransformFeedback if "
989 "current transform feedback is not active or paused."
990 << tcu::TestLog::EndMessage;
991
992 return false;
993 }
994
995 /* INVALID_OPERATION is generated by ResumeTransformFeedback if current
996 transform feedback is not active; */
997
998 gl.resumeTransformFeedback();
999
1000 if (GL_INVALID_OPERATION != gl.getError())
1001 {
1002 m_context.getTestContext().getLog() << tcu::TestLog::Message
1003 << "INVALID_OPERATION is not generated by ResumeTransformFeedback if "
1004 "current transform feedback is not active."
1005 << tcu::TestLog::EndMessage;
1006
1007 return false;
1008 }
1009
1010 /* Prepare program and buffer. */
1011 gl.useProgram(m_program_id_with_output);
1012
1013 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1014
1015 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1016
1017 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
1018
1019 /* INVALID_OPERATION is generated by DrawTransformFeedback when
1020 EndTransformFeedback was never called for the object named <id>. */
1021 gl.drawTransformFeedback(GL_POINTS, m_transform_feedback_object_0);
1022
1023 if (GL_INVALID_OPERATION != gl.getError())
1024 {
1025 m_context.getTestContext().getLog() << tcu::TestLog::Message
1026 << "INVALID_OPERATION is not generated by DrawTransformFeedback when "
1027 "EndTransformFeedback was never called for the object named <id>."
1028 << tcu::TestLog::EndMessage;
1029
1030 return false;
1031 }
1032
1033 /* Make Transform Feedback Active */
1034 gl.beginTransformFeedback(GL_POINTS);
1035
1036 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1037
1038 /* INVALID_OPERATION is generated by BindTransformFeedback if current
1039 transform feedback is active and not paused; */
1040
1041 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1042
1043 if (GL_INVALID_OPERATION != gl.getError())
1044 {
1045 gl.endTransformFeedback();
1046
1047 m_context.getTestContext().getLog() << tcu::TestLog::Message
1048 << "INVALID_OPERATION is not generated by BindTransformFeedback if current "
1049 "transform feedback is active and not paused."
1050 << tcu::TestLog::EndMessage;
1051
1052 return false;
1053 }
1054
1055 /* INVALID_OPERATION is generated by DeleteTransformFeedbacks if any of <ids>
1056 is active; */
1057
1058 gl.deleteTransformFeedbacks(1, &m_transform_feedback_object_0);
1059
1060 if (GL_INVALID_OPERATION != gl.getError())
1061 {
1062 gl.endTransformFeedback();
1063
1064 m_context.getTestContext().getLog()
1065 << tcu::TestLog::Message
1066 << "INVALID_OPERATION is not generated by DeleteTransformFeedbacks if any of <ids> is active."
1067 << tcu::TestLog::EndMessage;
1068
1069 return false;
1070 }
1071
1072 /* INVALID_OPERATION is generated by ResumeTransformFeedback if current
1073 transform feedback is not not paused; */
1074
1075 gl.resumeTransformFeedback();
1076
1077 if (GL_INVALID_OPERATION != gl.getError())
1078 {
1079 gl.endTransformFeedback();
1080
1081 m_context.getTestContext().getLog() << tcu::TestLog::Message
1082 << "INVALID_OPERATION is not generated by ResumeTransformFeedback if "
1083 "current transform feedback is not not paused."
1084 << tcu::TestLog::EndMessage;
1085
1086 return false;
1087 }
1088
1089 /* pause transform feedback */
1090
1091 gl.pauseTransformFeedback();
1092
1093 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
1094
1095 /* No error is generated by draw command when transform feedback is paused
1096 and primitive modes do not match; */
1097
1098 gl.drawArrays(GL_LINES, 0, 2);
1099
1100 if (GL_NO_ERROR != gl.getError())
1101 {
1102 gl.endTransformFeedback();
1103
1104 m_context.getTestContext().getLog() << tcu::TestLog::Message
1105 << "No error is not generated by draw command when transform feedback is "
1106 "paused and primitive modes do not match."
1107 << tcu::TestLog::EndMessage;
1108
1109 return false;
1110 }
1111
1112 /* INVALID_OPERATION is generated by LinkProgram when <program> is used by
1113 some transform feedback object that is currently not active; */
1114
1115 gl.linkProgram(m_program_id_with_output);
1116
1117 if (GL_INVALID_OPERATION != gl.getError())
1118 {
1119 m_context.getTestContext().getLog() << tcu::TestLog::Message
1120 << "INVALID_OPERATION was not generated by LinkProgram when <program> was "
1121 "used by some transform feedback object that is currently not active."
1122 << tcu::TestLog::EndMessage;
1123
1124 gl.endTransformFeedback();
1125
1126 return false;
1127 }
1128
1129 /* No error is generated by UseProgram when transform feedback is paused; */
1130
1131 gl.useProgram(0);
1132
1133 if (GL_NO_ERROR != gl.getError())
1134 {
1135 gl.endTransformFeedback();
1136
1137 m_context.getTestContext().getLog() << tcu::TestLog::Message
1138 << "glUseProgram unexpectedly failed when transform feedback is paused."
1139 << tcu::TestLog::EndMessage;
1140
1141 return false;
1142 }
1143
1144 gl.useProgram(m_program_id_with_output);
1145
1146 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1147
1148 /* End Transform Feedback and make draw. */
1149
1150 gl.endTransformFeedback();
1151 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1152
1153 /* INVALID_VALUE is generated by DrawTransformFeedback if <id> is not name of
1154 transform feedback object; */
1155
1156 unsigned short int invalid_name = 1;
1157
1158 while (gl.isTransformFeedback(invalid_name))
1159 {
1160 ++invalid_name;
1161
1162 /* Make sure that this loop ends someday, bad day. */
1163 if (invalid_name == USHRT_MAX)
1164 {
1165 m_context.getTestContext().getLog()
1166 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
1167 throw 0;
1168 }
1169 }
1170
1171 gl.drawTransformFeedback(GL_POINTS, (glw::GLuint)invalid_name);
1172
1173 if (GL_INVALID_VALUE != gl.getError())
1174 {
1175 gl.endTransformFeedback();
1176
1177 m_context.getTestContext().getLog() << tcu::TestLog::Message
1178 << "glUseProgram unexpectedly failed when transform feedback is paused."
1179 << tcu::TestLog::EndMessage;
1180
1181 return false;
1182 }
1183
1184 return true;
1185 }
1186
testExtension3(void)1187 bool gl3cts::TransformFeedback::APIErrors::testExtension3(void)
1188 {
1189 /* Functions handler */
1190 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1191
1192 /* INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
1193 GetQueryIndexediv when <target> is TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN and
1194 <index> exceeds limits of MAX_VERTEX_STREAMS
1195
1196 INVALID_VALUE is generated by BeginQueryIndexed, EndQueryIndexed and
1197 GetQueryIndexediv when <target> is PRIMITIVES_GENERATED and <index> exceeds
1198 limits of MAX_VERTEX_STREAMS */
1199
1200 glw::GLint max_vertex_streams = 0;
1201
1202 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
1203
1204 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1205
1206 if (max_vertex_streams == 0)
1207 {
1208 /* Nothing returned. */
1209 throw 0;
1210 }
1211
1212 ++max_vertex_streams;
1213
1214 static const glw::GLenum target[] = { GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, GL_PRIMITIVES_GENERATED };
1215 static const glw::GLchar* target_str[] = { STR(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN),
1216 STR(GL_PRIMITIVES_GENERATED) };
1217 static const glw::GLuint target_count = sizeof(target) / sizeof(target[0]);
1218
1219 for (glw::GLuint i = 0; i < target_count; ++i)
1220 {
1221 gl.beginQueryIndexed(target[i], max_vertex_streams, m_query_object);
1222
1223 if (GL_INVALID_VALUE != gl.getError())
1224 {
1225 m_context.getTestContext().getLog()
1226 << tcu::TestLog::Message << "INVALID_VALUE was not generated by BeginQueryIndexed, EndQueryIndexed and"
1227 "GetQueryIndexediv when <target> was "
1228 << target_str[i] << " and "
1229 "<index> exceeded limits of MAX_VERTEX_STREAMS."
1230 << tcu::TestLog::EndMessage;
1231 return false;
1232 }
1233
1234 gl.endQueryIndexed(target[i], max_vertex_streams);
1235
1236 if (GL_INVALID_VALUE != gl.getError())
1237 {
1238 m_context.getTestContext().getLog() << tcu::TestLog::Message
1239 << "INVALID_VALUE was not generated by EndQueryIndexed "
1240 "when <target> was "
1241 << target_str[i] << " and "
1242 "<index> exceeded limits of MAX_VERTEX_STREAMS."
1243 << tcu::TestLog::EndMessage;
1244 return false;
1245 }
1246
1247 glw::GLint param = 0;
1248
1249 gl.getQueryIndexediv(target[i], max_vertex_streams, GL_QUERY_COUNTER_BITS, ¶m);
1250
1251 if (GL_INVALID_VALUE != gl.getError())
1252 {
1253 m_context.getTestContext().getLog() << tcu::TestLog::Message << "INVALID_VALUE was not generated by "
1254 "GetQueryIndexediv when <target> was "
1255 << target_str[i] << " and "
1256 "<index> exceeded limits of MAX_VERTEX_STREAMS."
1257 << tcu::TestLog::EndMessage;
1258 return false;
1259 }
1260 }
1261
1262 /* INVALID_OPERATION is generated by EndQueryIndexed when name of active
1263 query at <index> of <target> is zero */
1264
1265 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
1266
1267 if (GL_INVALID_OPERATION != gl.getError())
1268 {
1269 m_context.getTestContext().getLog()
1270 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by EndQueryIndexed when name of active "
1271 "query at <index> of <target> is zero"
1272 << tcu::TestLog::EndMessage;
1273 return false;
1274 }
1275
1276 /* INVALID_VALUE is generated by DrawTransformFeedbackStream when <stream>
1277 exceeds limits of MAX_VERTEX_STREAMS */
1278
1279 gl.drawTransformFeedbackStream(GL_POINTS, m_transform_feedback_object_0, max_vertex_streams);
1280
1281 if (GL_INVALID_VALUE != gl.getError())
1282 {
1283 m_context.getTestContext().getLog()
1284 << tcu::TestLog::Message << "INVALID_VALUE was not generated by DrawTransformFeedbackStream when <stream> "
1285 "exceeded limits of MAX_VERTEX_STREAMS"
1286 << tcu::TestLog::EndMessage;
1287 return false;
1288 }
1289
1290 /* INVALID_OPERATION is generated by TransformFeedbackVaryings when
1291 <varyings> contains any of the special names while <bufferMode> is not
1292 INTERLEAVED_ATTRIBS */
1293
1294 static const glw::GLchar* tf_varying_names[] = { "gl_NextBuffer", "gl_SkipComponents1", "gl_SkipComponents2",
1295 "gl_SkipComponents3", "gl_SkipComponents4" };
1296 static const glw::GLuint tf_varying_names_count = sizeof(tf_varying_names) / sizeof(tf_varying_names[0]);
1297
1298 for (glw::GLuint i = 0; i < tf_varying_names_count; ++i)
1299 {
1300 gl.transformFeedbackVaryings(m_program_id_with_output, 1, &tf_varying_names[i], GL_SEPARATE_ATTRIBS);
1301
1302 if (GL_INVALID_OPERATION != gl.getError())
1303 {
1304 m_context.getTestContext().getLog()
1305 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when "
1306 "<varyings> contained any of the special names while <bufferMode> was "
1307 "GL_SEPARATE_ATTRIBS."
1308 << tcu::TestLog::EndMessage;
1309 return false;
1310 }
1311 }
1312
1313 /* INVALID_OPERATION is generated by TransformFeedbackVaryings when
1314 <varyings> contains more "gl_NextBuffer" entries than allowed limit of
1315 MAX_TRANSFORM_FEEDBACK_BUFFERS */
1316
1317 glw::GLint max_transform_feedback_buffers = 0;
1318
1319 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
1320
1321 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1322
1323 if (max_transform_feedback_buffers == 0)
1324 {
1325 /* Nothing returned. */
1326 throw 0;
1327 }
1328
1329 glw::GLint more_than_max_transform_feedback_buffers = max_transform_feedback_buffers + 1;
1330
1331 const glw::GLchar** tf_next_buffer_varying_names = new const glw::GLchar*[more_than_max_transform_feedback_buffers];
1332
1333 if (DE_NULL == tf_next_buffer_varying_names)
1334 {
1335 /* Allocation error. */
1336 throw 0;
1337 }
1338
1339 for (glw::GLint i = 0; i < more_than_max_transform_feedback_buffers; ++i)
1340 {
1341 tf_next_buffer_varying_names[i] = tf_varying_names[0];
1342 }
1343
1344 gl.transformFeedbackVaryings(m_program_id_with_output, more_than_max_transform_feedback_buffers,
1345 tf_next_buffer_varying_names, GL_INTERLEAVED_ATTRIBS);
1346
1347 delete[] tf_next_buffer_varying_names;
1348
1349 if (GL_INVALID_OPERATION != gl.getError())
1350 {
1351 m_context.getTestContext().getLog()
1352 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by TransformFeedbackVaryings when "
1353 "<varyings> contained more \"gl_NextBuffer\" entries than allowed limit of "
1354 "MAX_TRANSFORM_FEEDBACK_BUFFER."
1355 << tcu::TestLog::EndMessage;
1356 return false;
1357 }
1358
1359 return true;
1360 }
1361
testInstanced(void)1362 bool gl3cts::TransformFeedback::APIErrors::testInstanced(void)
1363 {
1364 /* Functions handler */
1365 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1366
1367 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
1368 bool is_tessellation = m_context.getContextInfo().isExtensionSupported("GL_ARB_tessellation_shader");
1369
1370 bool has_patches = is_at_least_gl_40 || is_tessellation;
1371
1372 /* INVALID_ENUM is generated by DrawTransformFeedbackInstanced and
1373 DrawTransformFeedbackStreamInstanced if <mode> is invalid */
1374
1375 glw::GLenum _supported_mode[] = { GL_POINTS,
1376 GL_LINE_STRIP,
1377 GL_LINE_LOOP,
1378 GL_LINES,
1379 GL_LINE_STRIP_ADJACENCY,
1380 GL_LINES_ADJACENCY,
1381 GL_TRIANGLE_STRIP,
1382 GL_TRIANGLE_FAN,
1383 GL_TRIANGLES,
1384 GL_TRIANGLE_STRIP_ADJACENCY,
1385 GL_TRIANGLES_ADJACENCY,
1386 GL_QUADS,
1387 GL_PATCHES };
1388
1389 std::set<glw::GLenum> supported_mode(_supported_mode,
1390 _supported_mode + sizeof(_supported_mode) / sizeof(_supported_mode[0]) - (has_patches ? 0 : 1));
1391
1392 int mode = 0;
1393
1394 while (supported_mode.find(mode) != supported_mode.end())
1395 {
1396 mode++;
1397 }
1398
1399 gl.drawTransformFeedbackInstanced(mode, m_transform_feedback_object_0, 1);
1400
1401 if (GL_INVALID_ENUM != gl.getError())
1402 {
1403 m_context.getTestContext().getLog() << tcu::TestLog::Message
1404 << "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and "
1405 "DrawTransformFeedbackStreamInstanced when <mode> was invalid."
1406 << tcu::TestLog::EndMessage;
1407 return false;
1408 }
1409
1410 gl.drawTransformFeedbackStreamInstanced(mode, m_transform_feedback_object_0, 0, 1);
1411
1412 if (GL_INVALID_ENUM != gl.getError())
1413 {
1414 m_context.getTestContext().getLog() << tcu::TestLog::Message
1415 << "INVALID_ENUM was not generated by DrawTransformFeedbackInstanced and "
1416 "DrawTransformFeedbackStreamInstanced when <mode> was invalid."
1417 << tcu::TestLog::EndMessage;
1418 return false;
1419 }
1420
1421 if (m_program_id_with_geometry_shader != 0) {
1422 /* INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
1423 DrawTransformFeedbackStreamInstanced if <mode> does not match geometry
1424 shader */
1425
1426 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1427
1428 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1429
1430 gl.useProgram(m_program_id_with_geometry_shader);
1431
1432 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1433
1434 gl.bindVertexArray(m_vertex_array_object);
1435
1436 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1437
1438 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1439
1440 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1441
1442 gl.beginTransformFeedback(GL_POINTS);
1443
1444 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1445
1446 gl.drawArrays(GL_POINTS, 0, 1);
1447
1448 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1449
1450 gl.endTransformFeedback();
1451
1452 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1453
1454 gl.drawTransformFeedbackInstanced(GL_LINES, m_transform_feedback_object_0, 1);
1455
1456 if (GL_INVALID_OPERATION != gl.getError())
1457 {
1458 m_context.getTestContext().getLog()
1459 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1460 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1461 << tcu::TestLog::EndMessage;
1462 return false;
1463 }
1464
1465 gl.drawTransformFeedbackStreamInstanced(GL_LINES, m_transform_feedback_object_0, 0, 1);
1466
1467 if (GL_INVALID_OPERATION != gl.getError())
1468 {
1469 m_context.getTestContext().getLog()
1470 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1471 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1472 << tcu::TestLog::EndMessage;
1473 return false;
1474 }
1475 }
1476
1477 /* All of the below tests concern themselves with GL_PATCHES and
1478 * tessellation shaders */
1479 if (m_program_id_with_tessellation_shaders == 0)
1480 {
1481 return true;
1482 }
1483
1484 /* INVALID_OPERATION is generated by DrawTransformFeedbackInstanced and
1485 DrawTransformFeedbackStreamInstanced if <mode> does not match tessellation */
1486
1487 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_0);
1488
1489 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1490
1491 gl.useProgram(m_program_id_with_tessellation_shaders);
1492
1493 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1494
1495 gl.bindVertexArray(m_vertex_array_object);
1496
1497 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
1498
1499 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer_0);
1500
1501 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
1502
1503 gl.beginTransformFeedback(GL_LINES);
1504
1505 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
1506
1507 gl.drawArrays(GL_PATCHES, 0, 2);
1508
1509 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
1510
1511 gl.endTransformFeedback();
1512
1513 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
1514
1515 gl.drawTransformFeedbackInstanced(GL_POINTS, m_transform_feedback_object_0, 1);
1516
1517 if (GL_INVALID_OPERATION != gl.getError())
1518 {
1519 m_context.getTestContext().getLog()
1520 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1521 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1522 << tcu::TestLog::EndMessage;
1523 return false;
1524 }
1525
1526 gl.drawTransformFeedbackStreamInstanced(GL_POINTS, m_transform_feedback_object_0, 0, 1);
1527
1528 if (GL_INVALID_OPERATION != gl.getError())
1529 {
1530 m_context.getTestContext().getLog()
1531 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1532 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1533 << tcu::TestLog::EndMessage;
1534 return false;
1535 }
1536
1537 /* INVALID_VALUE is generated by DrawTransformFeedbackStreamInstanced if
1538 <stream> is greater than or equal to MAX_VERTEX_STREAMS */
1539
1540 glw::GLint max_vertex_streams = 0;
1541
1542 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
1543
1544 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1545
1546 if (max_vertex_streams == 0)
1547 {
1548 /* Failed to query GL_MAX_VERTEX_STREAMS. */
1549 throw 0;
1550 }
1551
1552 glw::GLint more_than_max_vertex_streams = max_vertex_streams + 1;
1553
1554 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_0, more_than_max_vertex_streams, 1);
1555
1556 if (GL_INVALID_VALUE != gl.getError())
1557 {
1558 m_context.getTestContext().getLog()
1559 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1560 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1561 << tcu::TestLog::EndMessage;
1562 return false;
1563 }
1564
1565 /* INVALID_VALUE is generated by DrawTransformFeedbackInstanced and
1566 DrawTransformFeedbackStreamInstanced if <id> is not name of transform
1567 feedback object */
1568
1569 unsigned short int invalid_name = 1;
1570
1571 while (gl.isTransformFeedback(invalid_name))
1572 {
1573 ++invalid_name;
1574
1575 /* Make sure that this loop ends someday, bad day. */
1576 if (invalid_name == USHRT_MAX)
1577 {
1578 m_context.getTestContext().getLog()
1579 << tcu::TestLog::Message << "Cannot find unused trnasform feedback object." << tcu::TestLog::EndMessage;
1580 throw 0;
1581 }
1582 }
1583
1584 gl.drawTransformFeedbackInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 1);
1585
1586 if (GL_INVALID_VALUE != gl.getError())
1587 {
1588 gl.endTransformFeedback();
1589
1590 return false;
1591 }
1592
1593 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, (glw::GLuint)invalid_name, 0, 1);
1594
1595 if (GL_INVALID_VALUE != gl.getError())
1596 {
1597 gl.endTransformFeedback();
1598
1599 return false;
1600 }
1601
1602 /* INVALID_OPERATION is generated if by DrawTransformFeedbackStreamInstanced
1603 if EndTransformFeedback was never called for the object named <id>.
1604 return true */
1605
1606 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_transform_feedback_object_1);
1607
1608 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
1609
1610 gl.drawTransformFeedbackStreamInstanced(GL_PATCHES, m_transform_feedback_object_1, 0, 1);
1611
1612 if (GL_INVALID_OPERATION != gl.getError())
1613 {
1614 m_context.getTestContext().getLog()
1615 << tcu::TestLog::Message << "INVALID_OPERATION was not generated by DrawTransformFeedbackInstanced and "
1616 "DrawTransformFeedbackStreamInstanced if <mode> did not match geometry shader."
1617 << tcu::TestLog::EndMessage;
1618
1619 return false;
1620 }
1621
1622 return true;
1623 }
1624
1625 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_control_shader =
1626 "#version 400\n"
1627 "\n"
1628 "layout (vertices = 2 ) out;\n"
1629 "\n"
1630 "void main()\n"
1631 "{\n"
1632 " gl_TessLevelOuter[1] = 3.0;\n"
1633 " gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1634 "}\n";
1635
1636 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_tessellation_evaluation_shader =
1637 "#version 400\n"
1638 "\n"
1639 "layout(isolines, equal_spacing, ccw) in;\n"
1640 "\n"
1641 "out float result;\n"
1642 "\n"
1643 "void main()\n"
1644 "{\n"
1645 " result = 0.5;\n"
1646 " gl_Position = gl_in[0].gl_Position + gl_in[1].gl_Position + gl_in[2].gl_Position;\n"
1647 "}\n";
1648
1649 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_geometry_shader =
1650 "#version 150\n"
1651 "\n"
1652 "layout(points) in;\n"
1653 "layout(points, max_vertices = 2) out;\n"
1654 "\n"
1655 "out float result;\n"
1656 "\n"
1657 "void main()\n"
1658 "{\n"
1659 " gl_Position = gl_in[0].gl_Position + vec4(0.0, 0.0, 0.0, 0.0);\n"
1660 " result = 0.0;\n"
1661 " EmitVertex();\n"
1662 "\n"
1663 " gl_Position = gl_in[0].gl_Position + vec4(1.0, 0.0, 0.0, 0.0);\n"
1664 " result = 1.0;\n"
1665 " EmitVertex();\n"
1666 "}\n";
1667
1668 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_output =
1669 "#version 130\n"
1670 "\n"
1671 "out float result;\n"
1672 "\n"
1673 "void main()\n"
1674 "{\n"
1675 " result = float(gl_VertexID);\n"
1676 " gl_Position = vec4(1.0);\n"
1677 "}\n";
1678
1679 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_with_input_output =
1680 "#version 130\n"
1681 "\n"
1682 "in float v_input;\n"
1683 "\n"
1684 "out float result;\n"
1685 "\n"
1686 "void main()\n"
1687 "{\n"
1688 " result = float(gl_VertexID);\n"
1689 " gl_Position = vec4(v_input);\n"
1690 "}\n";
1691
1692 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_vertex_shader_without_output =
1693 "#version 130\n"
1694 "\n"
1695 "void main()\n"
1696 "{\n"
1697 " gl_Position = vec4(1.0);\n"
1698 "}\n";
1699
1700 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::s_fragment_shader = "#version 130\n"
1701 "\n"
1702 "out vec4 color;\n"
1703 "\n"
1704 "void main()\n"
1705 "{\n"
1706 " color = vec4(1.0);\n"
1707 "}\n";
1708
1709 const glw::GLchar* gl3cts::TransformFeedback::APIErrors::m_varying_name = "result";
1710
1711 const glw::GLfloat gl3cts::TransformFeedback::APIErrors::m_buffer_1_data[] = { 3.14159265359f, 2.7182818f };
1712
1713 const glw::GLsizei gl3cts::TransformFeedback::APIErrors::m_buffer_1_size =
1714 sizeof(gl3cts::TransformFeedback::APIErrors::m_buffer_1_data);
1715
1716 /*-----------------------------------------------------------------------------------------------*/
1717
LinkingErrors(deqp::Context & context)1718 gl3cts::TransformFeedback::LinkingErrors::LinkingErrors(deqp::Context& context)
1719 : deqp::TestCase(context, "linking_errors_test", "Transform Feedback Linking Errors Test"), m_context(context)
1720 {
1721 /* Left intentionally blank. */
1722 }
1723
~LinkingErrors(void)1724 gl3cts::TransformFeedback::LinkingErrors::~LinkingErrors(void)
1725 {
1726 }
1727
iterate(void)1728 tcu::TestNode::IterateResult gl3cts::TransformFeedback::LinkingErrors::iterate(void)
1729 {
1730 bool is_ok = true;
1731 bool test_error = false;
1732
1733 try
1734 {
1735 is_ok = is_ok && testNoVertexNoGeometry();
1736 is_ok = is_ok && testInvalidVarying();
1737 is_ok = is_ok && testRepeatedVarying();
1738 is_ok = is_ok && testTooManyVaryings();
1739 }
1740 catch (...)
1741 {
1742 is_ok = false;
1743 test_error = true;
1744 }
1745
1746 /* Result's setup. */
1747 if (is_ok)
1748 {
1749 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1750 }
1751 else
1752 {
1753 if (test_error)
1754 {
1755 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1756 }
1757 else
1758 {
1759 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1760 }
1761 }
1762
1763 return STOP;
1764 }
1765
testNoVertexNoGeometry(void)1766 bool gl3cts::TransformFeedback::LinkingErrors::testNoVertexNoGeometry(void)
1767 {
1768 /* Functions handler */
1769 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1770
1771 /* Check if link process fails under the following conditions:
1772 <count> specified by TransformFeedbackVaryings is non-zero and program has
1773 neither vertex nor geometry shader; */
1774
1775 glw::GLint linking_status = 1;
1776
1777 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1778 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, NULL, s_fragment_shader,
1779 &s_valid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status);
1780
1781 if ((GL_FALSE != linking_status) || program)
1782 {
1783 m_context.getTestContext().getLog() << tcu::TestLog::Message
1784 << "Linking unexpectedly succeded when Transform Feedback varying was "
1785 "specified but program had neither vertex nor geometry shader stages."
1786 << tcu::TestLog::EndMessage;
1787
1788 if (program)
1789 {
1790 gl.deleteProgram(program);
1791 }
1792
1793 return false;
1794 }
1795
1796 /* Log success. */
1797 m_context.getTestContext().getLog() << tcu::TestLog::Message
1798 << "Linking failed as expected when Transform Feedback varying was specified "
1799 "but program had neither vertex nor geometry shader stages."
1800 << tcu::TestLog::EndMessage;
1801
1802 return true;
1803 }
1804
testInvalidVarying(void)1805 bool gl3cts::TransformFeedback::LinkingErrors::testInvalidVarying(void)
1806 {
1807 /* Functions handler */
1808 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1809
1810 /* Check if link process fails under the following conditions:
1811 <varyings> specified by TransformFeedbackVaryings contains name of
1812 variable that is not available for capture; */
1813
1814 std::string vertex_shader(s_vertex_shader_template);
1815
1816 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1817 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "in float data;\n");
1818 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS", "");
1819
1820 glw::GLint linking_status = 1;
1821
1822 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1823 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1824 &s_invalid_transform_feedback_varying, 1, GL_INTERLEAVED_ATTRIBS, false, &linking_status);
1825
1826 if ((GL_FALSE != linking_status) || program)
1827 {
1828 m_context.getTestContext().getLog()
1829 << tcu::TestLog::Message
1830 << "Linking unexpectedly succeded when Transform Feedback varying was specified with name of variable ("
1831 << s_invalid_transform_feedback_varying << ") that is not available for capture."
1832 << tcu::TestLog::EndMessage;
1833
1834 if (program)
1835 {
1836 gl.deleteProgram(program);
1837 }
1838
1839 return false;
1840 }
1841
1842 /* Log success. */
1843 m_context.getTestContext().getLog()
1844 << tcu::TestLog::Message
1845 << "Linking failed as expected when Transform Feedback varying was specified with name of variable ("
1846 << s_invalid_transform_feedback_varying << ") that is not available for capture." << tcu::TestLog::EndMessage;
1847
1848 return true;
1849 }
1850
testRepeatedVarying(void)1851 bool gl3cts::TransformFeedback::LinkingErrors::testRepeatedVarying(void)
1852 {
1853 /* Functions handler */
1854 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1855
1856 /* Check if link process fails under the following conditions:
1857 <varyings> specified by TransformFeedbackVaryings contains name of
1858 variable more than once; */
1859
1860 std::string vertex_shader(s_vertex_shader_template);
1861
1862 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1863 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", "out float result;\n");
1864 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
1865 " result = 0.577215664901532;\n");
1866
1867 glw::GLint linking_status = 1;
1868
1869 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1870 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1871 s_repeated_transform_feedback_varying, s_repeated_transform_feedback_varying_count, GL_INTERLEAVED_ATTRIBS,
1872 false, &linking_status);
1873
1874 if ((GL_FALSE != linking_status) || program)
1875 {
1876 m_context.getTestContext().getLog()
1877 << tcu::TestLog::Message
1878 << "Linking unexpectedly succeded when Transform Feedback varying was specified twice."
1879 << tcu::TestLog::EndMessage;
1880
1881 if (program)
1882 {
1883 gl.deleteProgram(program);
1884 }
1885
1886 return false;
1887 }
1888
1889 /* Log success. */
1890 m_context.getTestContext().getLog()
1891 << tcu::TestLog::Message << "Linking failed as expected when Transform Feedback varying was specified twice."
1892 << tcu::TestLog::EndMessage;
1893
1894 return true;
1895 }
1896
testTooManyVaryings(void)1897 bool gl3cts::TransformFeedback::LinkingErrors::testTooManyVaryings(void)
1898 {
1899 /* Functions handler */
1900 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1901
1902 /* Check if link process fails under the following conditions:
1903 number of components specified to capture exceeds limits
1904 MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS or
1905 MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS. */
1906
1907 /* Fetching limits. */
1908 glw::GLint max_transform_feedback_separate_components = 0;
1909 glw::GLint max_transform_feedback_interleaved_components = 0;
1910
1911 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
1912
1913 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1914
1915 if (max_transform_feedback_separate_components == 0)
1916 {
1917 throw 0;
1918 }
1919
1920 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
1921
1922 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
1923
1924 if (max_transform_feedback_interleaved_components == 0)
1925 {
1926 throw 0;
1927 }
1928
1929 glw::GLint more_than_max_transform_feedback_components =
1930 deMax32(max_transform_feedback_separate_components, max_transform_feedback_interleaved_components) + 1;
1931
1932 /* Preparing source code. */
1933 std::string vertex_shader(s_vertex_shader_template);
1934 std::string transform_feedback_variable_declarations("");
1935 std::string transform_feedback_variable_setters("");
1936 std::vector<std::string> transform_feedback_varyings(more_than_max_transform_feedback_components);
1937 std::vector<const glw::GLchar*> transform_feedback_varyings_c(more_than_max_transform_feedback_components);
1938
1939 for (glw::GLint i = 0; i < more_than_max_transform_feedback_components; ++i)
1940 {
1941 std::string varying = "result_";
1942 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
1943
1944 transform_feedback_varyings[i] = varying;
1945
1946 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
1947
1948 transform_feedback_variable_declarations.append("out float ");
1949 transform_feedback_variable_declarations.append(varying);
1950 transform_feedback_variable_declarations.append(";\n");
1951
1952 transform_feedback_variable_setters.append(" ");
1953 transform_feedback_variable_setters.append(varying);
1954 transform_feedback_variable_setters.append(" = ");
1955 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * i));
1956 transform_feedback_variable_setters.append(".0;\n");
1957 }
1958
1959 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
1960 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
1961 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
1962 transform_feedback_variable_setters);
1963
1964 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
1965 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1966 &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_INTERLEAVED_ATTRIBS);
1967
1968 /* Note: we check for program as not only linking shall fail, but also glTransformFeedbackVaryings shall return an error. */
1969
1970 if (program)
1971 {
1972 m_context.getTestContext().getLog() << tcu::TestLog::Message
1973 << "Linking unexpectedly succeded when too many Transform Feedback varying "
1974 "were specified in INTERLEAVED mode."
1975 << tcu::TestLog::EndMessage;
1976
1977 if (program)
1978 {
1979 gl.deleteProgram(program);
1980 }
1981
1982 return false;
1983 }
1984
1985 program = gl3cts::TransformFeedback::Utilities::buildProgram(
1986 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader,
1987 &transform_feedback_varyings_c[0], more_than_max_transform_feedback_components, GL_SEPARATE_ATTRIBS);
1988
1989 if (program)
1990 {
1991 m_context.getTestContext().getLog() << tcu::TestLog::Message
1992 << "Linking unexpectedly succeded when too many Transform Feedback "
1993 "varyings were specified in SEPARATE mode."
1994 << tcu::TestLog::EndMessage;
1995
1996 if (program)
1997 {
1998 gl.deleteProgram(program);
1999 }
2000
2001 return false;
2002 }
2003
2004 /* Log success. */
2005 m_context.getTestContext().getLog()
2006 << tcu::TestLog::Message
2007 << "Linking failed as expected when too many Transform Feedback varyings were specified."
2008 << tcu::TestLog::EndMessage;
2009
2010 return true;
2011 }
2012
2013 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_fragment_shader = "#version 130\n"
2014 "\n"
2015 "out vec4 color;\n"
2016 "\n"
2017 "void main()\n"
2018 "{\n"
2019 " color = vec4(1.0);\n"
2020 "}\n";
2021
2022 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_vertex_shader_template =
2023 "#version 130\n"
2024 "\n"
2025 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
2026 "\n"
2027 "void main()\n"
2028 "{\n"
2029 "TEMPLATE_OUTPUT_SETTERS"
2030 "\n"
2031 " gl_Position = vec4(1.618033988749);\n"
2032 "}\n";
2033
2034 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_valid_transform_feedback_varying = "result";
2035
2036 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_invalid_transform_feedback_varying = "data";
2037
2038 const glw::GLchar* gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying[] = { "result",
2039 "result" };
2040
2041 const glw::GLsizei gl3cts::TransformFeedback::LinkingErrors::s_repeated_transform_feedback_varying_count =
2042 sizeof(s_repeated_transform_feedback_varying) / sizeof(s_repeated_transform_feedback_varying[0]);
2043
2044 /*-----------------------------------------------------------------------------------------------*/
2045
2046 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_interleaved_components = 64;
2047 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_attribs = 4;
2048 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_separate_components = 4;
2049 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_transform_feedback_buffers = 4;
2050 const glw::GLint gl3cts::TransformFeedback::Limits::s_min_value_of_max_vertex_streams = 1;
2051
Limits(deqp::Context & context)2052 gl3cts::TransformFeedback::Limits::Limits(deqp::Context& context)
2053 : deqp::TestCase(context, "limits_test", "Transform Feedback Limits Test"), m_context(context)
2054 {
2055 }
2056
~Limits(void)2057 gl3cts::TransformFeedback::Limits::~Limits(void)
2058 {
2059 }
2060
iterate(void)2061 tcu::TestNode::IterateResult gl3cts::TransformFeedback::Limits::iterate(void)
2062 {
2063 /* Initializations. */
2064 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2065 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
2066
2067 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2068 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
2069
2070 bool is_ok = true;
2071 bool test_error = false;
2072
2073 /* Tests. */
2074 try
2075 {
2076 if (is_at_least_gl_30 || is_ext_tf_1)
2077 {
2078 is_ok = is_ok && test_max_transform_feedback_interleaved_components();
2079 is_ok = is_ok && test_max_transform_feedback_separate_attribs();
2080 is_ok = is_ok && test_max_transform_feedback_separate_components();
2081 }
2082
2083 if (is_at_least_gl_40 || is_arb_tf_3)
2084 {
2085 is_ok = is_ok && test_max_transform_feedback_buffers();
2086 is_ok = is_ok && test_max_vertex_streams();
2087 }
2088 }
2089 catch (...)
2090 {
2091 is_ok = false;
2092 test_error = true;
2093 }
2094
2095 /* Result's setup. */
2096 if (is_ok)
2097 {
2098 /* Log success. */
2099 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Limits are in range of specification."
2100 << tcu::TestLog::EndMessage;
2101
2102 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2103 }
2104 else
2105 {
2106 if (test_error)
2107 {
2108 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2109 }
2110 else
2111 {
2112 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2113 }
2114 }
2115
2116 return STOP;
2117 }
2118
test_max_transform_feedback_interleaved_components(void)2119 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_interleaved_components(void)
2120 {
2121 /* Functions handler */
2122 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2123
2124 /* Check that MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is at least 64. */
2125 glw::GLint max_transform_feedback_interleaved_components = 0;
2126
2127 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &max_transform_feedback_interleaved_components);
2128
2129 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2130
2131 if (max_transform_feedback_interleaved_components < s_min_value_of_max_transform_feedback_interleaved_components)
2132 {
2133 m_context.getTestContext().getLog()
2134 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS is equal to "
2135 << max_transform_feedback_interleaved_components << " which is less than expected "
2136 << s_min_value_of_max_transform_feedback_interleaved_components << "." << tcu::TestLog::EndMessage;
2137 return false;
2138 }
2139
2140 return true;
2141 }
2142
test_max_transform_feedback_separate_attribs(void)2143 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_attribs(void)
2144 {
2145 /* Functions handler */
2146 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2147
2148 /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is at least 4. */
2149 glw::GLint max_transform_feedback_separate_attribs = 0;
2150
2151 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &max_transform_feedback_separate_attribs);
2152
2153 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2154
2155 if (max_transform_feedback_separate_attribs < s_min_value_of_max_transform_feedback_separate_attribs)
2156 {
2157 m_context.getTestContext().getLog()
2158 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS is equal to "
2159 << max_transform_feedback_separate_attribs << " which is less than expected "
2160 << s_min_value_of_max_transform_feedback_separate_attribs << "." << tcu::TestLog::EndMessage;
2161 return false;
2162 }
2163
2164 return true;
2165 }
2166
test_max_transform_feedback_separate_components(void)2167 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_separate_components(void)
2168 {
2169 /* Functions handler */
2170 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2171
2172 /* Check that MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is at least 4. */
2173 glw::GLint max_transform_feedback_separate_components = 0;
2174
2175 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
2176
2177 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2178
2179 if (max_transform_feedback_separate_components < s_min_value_of_max_transform_feedback_separate_components)
2180 {
2181 m_context.getTestContext().getLog()
2182 << tcu::TestLog::Message << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS is equal to "
2183 << max_transform_feedback_separate_components << " which is less than expected "
2184 << s_min_value_of_max_transform_feedback_separate_components << "." << tcu::TestLog::EndMessage;
2185 return false;
2186 }
2187
2188 return true;
2189 }
2190
test_max_transform_feedback_buffers(void)2191 bool gl3cts::TransformFeedback::Limits::test_max_transform_feedback_buffers(void)
2192 {
2193 /* Functions handler */
2194 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2195
2196 /* Check that MAX_TRANSFORM_FEEDBACK_BUFFERS is at least 4. */
2197 glw::GLint max_transform_feedback_buffers = 0;
2198
2199 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_BUFFERS, &max_transform_feedback_buffers);
2200
2201 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2202
2203 if (max_transform_feedback_buffers < s_min_value_of_max_transform_feedback_buffers)
2204 {
2205 m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_TRANSFORM_FEEDBACK_BUFFERS is equal to "
2206 << max_transform_feedback_buffers << " which is less than expected "
2207 << s_min_value_of_max_transform_feedback_buffers << "."
2208 << tcu::TestLog::EndMessage;
2209 return false;
2210 }
2211
2212 return true;
2213 }
2214
test_max_vertex_streams(void)2215 bool gl3cts::TransformFeedback::Limits::test_max_vertex_streams(void)
2216 {
2217 /* Functions handler */
2218 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2219
2220 /* Check that MAX_VERTEX_STREAMS is at least 1. */
2221 glw::GLint max_vertex_streams = 0;
2222
2223 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
2224
2225 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2226
2227 if (max_vertex_streams < s_min_value_of_max_vertex_streams)
2228 {
2229 m_context.getTestContext().getLog() << tcu::TestLog::Message << "MAX_VERTEX_STREAMS is equal to "
2230 << max_vertex_streams << " which is less than expected "
2231 << s_min_value_of_max_vertex_streams << "." << tcu::TestLog::EndMessage;
2232 return false;
2233 }
2234
2235 return true;
2236 }
2237
2238 /*-----------------------------------------------------------------------------------------------*/
2239
CaptureVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)2240 gl3cts::TransformFeedback::CaptureVertexInterleaved::CaptureVertexInterleaved(deqp::Context& context,
2241 const char* test_name,
2242 const char* test_description)
2243 : deqp::TestCase(context, test_name, test_description)
2244 , m_context(context)
2245 , m_program(0)
2246 , m_framebuffer(0)
2247 , m_renderbuffer(0)
2248 , m_buffer(0)
2249 , m_buffer_size(0)
2250 , m_vertex_array_object(0)
2251 , m_max_transform_feedback_components(0)
2252 , m_attrib_type(GL_INTERLEAVED_ATTRIBS)
2253 , m_max_vertices_drawn(8)
2254 , m_glBindBufferOffsetEXT(DE_NULL)
2255 {
2256 }
2257
~CaptureVertexInterleaved(void)2258 gl3cts::TransformFeedback::CaptureVertexInterleaved::~CaptureVertexInterleaved(void)
2259 {
2260 }
2261
iterate(void)2262 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureVertexInterleaved::iterate(void)
2263 {
2264 /* Functions handler */
2265 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2266
2267 /* Initializations. */
2268 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2269 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2270
2271 bool is_ok = true;
2272 bool test_error = false;
2273
2274 try
2275 {
2276 if (is_ext_tf_1)
2277 {
2278 /* Extension query. */
2279 m_glBindBufferOffsetEXT =
2280 (BindBufferOffsetEXT_ProcAddress)m_context.getRenderContext().getProcAddress("glBindBufferOffsetEXT");
2281
2282 if (DE_NULL == m_glBindBufferOffsetEXT)
2283 {
2284 throw 0;
2285 }
2286 }
2287
2288 if (is_at_least_gl_30 || is_ext_tf_1)
2289 {
2290 fetchLimits();
2291 buildProgram();
2292 createFramebuffer();
2293 createTransformFeedbackBuffer();
2294 createVertexArrayObject();
2295
2296 gl.useProgram(m_program);
2297
2298 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2299
2300 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case)
2301 {
2302 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT))
2303 {
2304 continue;
2305 }
2306
2307 bindBuffer((BindBufferCase)i_bind_case);
2308
2309 for (glw::GLuint i_primitive_case = 0; (i_primitive_case < s_primitive_cases_count) && is_ok;
2310 ++i_primitive_case)
2311 {
2312 draw(i_primitive_case);
2313
2314 is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]);
2315 is_ok = is_ok && checkTransformFeedbackBuffer((BindBufferCase)i_bind_case,
2316 s_primitive_cases[i_primitive_case]);
2317 }
2318 }
2319 }
2320 }
2321 catch (...)
2322 {
2323 is_ok = false;
2324 test_error = true;
2325 }
2326
2327 /* Clean objects. */
2328 clean();
2329
2330 /* Result's setup. */
2331 if (is_ok)
2332 {
2333 /* Log success. */
2334 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Vertex have passed."
2335 << tcu::TestLog::EndMessage;
2336
2337 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2338 }
2339 else
2340 {
2341 if (test_error)
2342 {
2343 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2344 }
2345 else
2346 {
2347 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2348 }
2349 }
2350
2351 return STOP;
2352 }
2353
fetchLimits(void)2354 void gl3cts::TransformFeedback::CaptureVertexInterleaved::fetchLimits(void)
2355 {
2356 /* Functions handler */
2357 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2358
2359 /* Fetching limits. */
2360 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components);
2361
2362 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2363
2364 if (m_max_transform_feedback_components == 0)
2365 {
2366 throw 0;
2367 }
2368
2369 glw::GLint max_varyings_components = 0;
2370
2371 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components);
2372
2373 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2374
2375 if (max_varyings_components == 0)
2376 {
2377 throw 0;
2378 }
2379
2380 if (m_max_transform_feedback_components > max_varyings_components)
2381 {
2382 m_max_transform_feedback_components = max_varyings_components;
2383 }
2384 }
2385
buildProgram(void)2386 void gl3cts::TransformFeedback::CaptureVertexInterleaved::buildProgram(void)
2387 {
2388 /* Functions handler */
2389 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2390
2391 /* Preparing source code. */
2392 std::string vertex_shader(s_vertex_shader_source_code_template); /* Storage for vertex shader source code. */
2393 std::string transform_feedback_variable_declarations(
2394 ""); /* String to contain all custom outputs from vertex shader. */
2395 std::string transform_feedback_variable_setters(
2396 ""); /* String containing all initializations of custom outputs from vertex shader. */
2397 std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */
2398 std::vector<const glw::GLchar*> transform_feedback_varyings_c(
2399 m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */
2400
2401 glw::GLint user_defined_transform_feedback_interleaved_varyings_count =
2402 m_max_transform_feedback_components /* total max to be written by the shader */
2403 / 4 /* components per vec4 */
2404 - 1 /* gl_Position */;
2405
2406 glw::GLint all_transform_feedback_interleaved_varyings_count =
2407 user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */;
2408
2409 /* Most of varyings is declarated output variables. */
2410 for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i)
2411 {
2412 std::string varying = "result_";
2413 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
2414
2415 transform_feedback_varyings[i] = varying;
2416
2417 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
2418
2419 transform_feedback_variable_declarations.append("out vec4 ");
2420 transform_feedback_variable_declarations.append(varying);
2421 transform_feedback_variable_declarations.append(";\n");
2422
2423 transform_feedback_variable_setters.append(" ");
2424 transform_feedback_variable_setters.append(varying);
2425 transform_feedback_variable_setters.append(" = vec4(");
2426 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4));
2427 transform_feedback_variable_setters.append(".0, ");
2428 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1));
2429 transform_feedback_variable_setters.append(".0, ");
2430 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2));
2431 transform_feedback_variable_setters.append(".0, ");
2432 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3));
2433 transform_feedback_variable_setters.append(".0);\n");
2434 }
2435
2436 /* Last four varying components are gl_Position components. */
2437 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count] = "gl_Position";
2438
2439 transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count] =
2440 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count].c_str();
2441
2442 /* Preprocess vertex shader source code template. */
2443 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2444 vertex_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
2445 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(vertex_shader, "TEMPLATE_OUTPUT_SETTERS",
2446 transform_feedback_variable_setters);
2447 vertex_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
2448 vertex_shader, "TEMPLATE_RASTERIZATION_EPSILON",
2449 gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon));
2450
2451 /* Compile, link and check. */
2452 m_program = gl3cts::TransformFeedback::Utilities::buildProgram(
2453 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, vertex_shader.c_str(), s_fragment_shader_source_code,
2454 &transform_feedback_varyings_c[0], all_transform_feedback_interleaved_varyings_count, m_attrib_type);
2455
2456 if (0 == m_program)
2457 {
2458 throw 0;
2459 }
2460 }
2461
createFramebuffer(void)2462 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createFramebuffer(void)
2463 {
2464 /* Functions handler */
2465 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2466
2467 /* Setting clear color */
2468 gl.clearColor(0.f, 0.f, 0.f, 1.f);
2469 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
2470
2471 /* Creating framebuffer */
2472 gl.genFramebuffers(1, &m_framebuffer);
2473 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
2474
2475 gl.genRenderbuffers(1, &m_renderbuffer);
2476 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
2477
2478 gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
2479 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
2480
2481 gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
2482 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
2483
2484 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32F, s_framebuffer_size, s_framebuffer_size);
2485 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
2486
2487 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
2488 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
2489
2490 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
2491 {
2492 throw 0;
2493 }
2494
2495 gl.viewport(0, 0, s_framebuffer_size, s_framebuffer_size);
2496 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
2497 }
2498
createTransformFeedbackBuffer(void)2499 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer(void)
2500 {
2501 /* Functions handler */
2502 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2503
2504 /* Creating xfb buffer */
2505 gl.genBuffers(1, &m_buffer);
2506 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
2507
2508 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer);
2509 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
2510
2511 m_buffer_size =
2512 static_cast<glw::GLuint>(m_max_transform_feedback_components * m_max_vertices_drawn * sizeof(glw::GLfloat));
2513
2514 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ);
2515 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
2516 }
2517
createVertexArrayObject(void)2518 void gl3cts::TransformFeedback::CaptureVertexInterleaved::createVertexArrayObject(void)
2519 {
2520 /* Functions handler */
2521 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2522
2523 /* VAO Creations */
2524 gl.genVertexArrays(1, &m_vertex_array_object);
2525 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
2526
2527 gl.bindVertexArray(m_vertex_array_object);
2528 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
2529 }
2530
draw(glw::GLuint primitive_case)2531 void gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(glw::GLuint primitive_case)
2532 {
2533 /* Functions handler */
2534 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2535
2536 /* Draw */
2537 gl.clear(GL_COLOR_BUFFER_BIT);
2538 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
2539
2540 gl.beginTransformFeedback(s_primitive_cases_xfb[primitive_case]);
2541 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedbac call failed.");
2542
2543 gl.drawElements(s_primitive_cases[primitive_case], s_element_indices_counts[primitive_case], GL_UNSIGNED_INT,
2544 s_element_indices[primitive_case]);
2545 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawElements call failed.");
2546
2547 gl.endTransformFeedback();
2548 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed.");
2549 }
2550
checkFramebuffer(glw::GLenum primitive_type UNUSED)2551 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkFramebuffer(glw::GLenum primitive_type UNUSED)
2552 {
2553 /* Functions handler */
2554 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2555
2556 /* Fetch framebuffer. */
2557 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
2558
2559 if (s_framebuffer_size > 0)
2560 {
2561 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
2562 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
2563 }
2564
2565 /* Check results.
2566 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
2567 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
2568 {
2569 if (fabs(*i - 0.5f) > 0.0625f /* precision */)
2570 {
2571 return false;
2572 }
2573 }
2574
2575 return true;
2576 }
2577
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)2578 bool gl3cts::TransformFeedback::CaptureVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
2579 glw::GLenum primitive_type)
2580 {
2581 /* Functions handler */
2582 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2583
2584 /* Check */
2585 glw::GLuint number_of_vertices = 0;
2586
2587 switch (primitive_type)
2588 {
2589 case GL_POINTS:
2590 number_of_vertices = 4;
2591 break;
2592 case GL_LINES:
2593 number_of_vertices = 4;
2594 break;
2595 case GL_LINE_LOOP:
2596 number_of_vertices = 8;
2597 break;
2598 case GL_LINE_STRIP:
2599 number_of_vertices = 6;
2600 break;
2601 case GL_TRIANGLES:
2602 number_of_vertices = 6;
2603 break;
2604 case GL_TRIANGLE_STRIP:
2605 number_of_vertices = 6;
2606 break;
2607 case GL_TRIANGLE_FAN:
2608 number_of_vertices = 6;
2609 break;
2610 default:
2611 throw 0;
2612 }
2613
2614 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
2615 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
2616
2617 bool is_ok = true;
2618
2619 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
2620 {
2621 for (glw::GLint i = 0; i < m_max_transform_feedback_components - 4; ++i)
2622 {
2623 glw::GLfloat result = results[i + j * m_max_transform_feedback_components];
2624 glw::GLfloat reference = (glw::GLfloat)(i);
2625
2626 if (fabs(result - reference) > 0.125 /* precision */)
2627 {
2628 is_ok = false;
2629
2630 break;
2631 }
2632 }
2633
2634 /* gl_Position */
2635 glw::GLfloat result[4] = { results[(j + 1) * m_max_transform_feedback_components - 4],
2636 results[(j + 1) * m_max_transform_feedback_components - 3],
2637 results[(j + 1) * m_max_transform_feedback_components - 2],
2638 results[(j + 1) * m_max_transform_feedback_components - 1] };
2639
2640 if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
2641 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
2642 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */))
2643 {
2644 is_ok = false;
2645
2646 break;
2647 }
2648 }
2649
2650 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2651 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2652
2653 return is_ok;
2654 }
2655
bindBuffer(BindBufferCase bind_case)2656 void gl3cts::TransformFeedback::CaptureVertexInterleaved::bindBuffer(BindBufferCase bind_case)
2657 {
2658 /* Functions handler */
2659 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2660
2661 switch (bind_case)
2662 {
2663 case BIND_BUFFER_BASE_CASE:
2664 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer);
2665 break;
2666 case BIND_BUFFER_RANGE_CASE:
2667 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0, m_buffer_size);
2668 break;
2669 case BIND_BUFFER_OFFSET_CASE:
2670 if (DE_NULL == m_glBindBufferOffsetEXT)
2671 {
2672 throw 0;
2673 }
2674 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_buffer, 0);
2675 break;
2676 default:
2677 throw 0;
2678 }
2679 }
2680
clean(void)2681 void gl3cts::TransformFeedback::CaptureVertexInterleaved::clean(void)
2682 {
2683 /* Functions handler */
2684 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2685
2686 if (m_program)
2687 {
2688 gl.deleteProgram(m_program);
2689
2690 m_program = 0;
2691 }
2692
2693 if (m_framebuffer)
2694 {
2695 gl.deleteFramebuffers(1, &m_framebuffer);
2696
2697 m_framebuffer = 0;
2698 }
2699
2700 if (m_renderbuffer)
2701 {
2702 gl.deleteRenderbuffers(1, &m_renderbuffer);
2703
2704 m_renderbuffer = 0;
2705 }
2706
2707 cleanBuffer();
2708
2709 if (m_vertex_array_object)
2710 {
2711 gl.deleteVertexArrays(1, &m_vertex_array_object);
2712
2713 m_vertex_array_object = 0;
2714 }
2715 }
2716
cleanBuffer(void)2717 void gl3cts::TransformFeedback::CaptureVertexInterleaved::cleanBuffer(void)
2718 {
2719 /* Functions handler */
2720 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2721
2722 if (m_buffer)
2723 {
2724 gl.deleteBuffers(1, &m_buffer);
2725
2726 m_buffer = 0;
2727 }
2728 }
2729
2730 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_vertex_shader_source_code_template =
2731 "#version 130\n"
2732 "\n"
2733 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
2734 "\n"
2735 "void main()\n"
2736 "{\n"
2737 "TEMPLATE_OUTPUT_SETTERS"
2738 "\n"
2739 " vec4 position = vec4(0.0);\n"
2740 "\n"
2741 " /* Note: The points are moved 0.0625 from the borders to\n"
2742 " reduce non-XFB related rasterization problems. */\n"
2743 " switch(gl_VertexID)\n"
2744 " {\n"
2745 " case 0:\n"
2746 " position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
2747 "1.0);\n"
2748 " break;\n"
2749 " case 1:\n"
2750 " position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
2751 "1.0);\n"
2752 " break;\n"
2753 " case 2:\n"
2754 " position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
2755 "1.0);\n"
2756 " break;\n"
2757 " case 3:\n"
2758 " position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
2759 "1.0);\n"
2760 " break;\n"
2761 " }\n"
2762 "\n"
2763 " gl_Position = position;\n"
2764 "}\n";
2765
2766 const glw::GLchar* gl3cts::TransformFeedback::CaptureVertexInterleaved::s_fragment_shader_source_code =
2767 "#version 130\n"
2768 "\n"
2769 "out vec4 color;\n"
2770 "\n"
2771 "void main()\n"
2772 "{\n"
2773 " color = vec4(0.5);\n"
2774 "}\n";
2775
2776 const glw::GLuint
2777 gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices[][s_max_element_indices_count] = {
2778 { 0, 1, 2, 3 }, { 0, 1, 2, 3 }, { 0, 1, 3, 2 }, { 0, 1, 3, 2 },
2779 { 2, 0, 1, 2, 1, 3 }, { 0, 1, 2, 3 }, { 2, 0, 1, 3 }
2780 };
2781
2782 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_count =
2783 sizeof(s_element_indices) / sizeof(s_element_indices[0]);
2784
2785 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases[] = {
2786 GL_POINTS, GL_LINES, GL_LINE_LOOP, GL_LINE_STRIP, GL_TRIANGLES, GL_TRIANGLE_STRIP, GL_TRIANGLE_FAN
2787 };
2788
2789 const glw::GLenum gl3cts::TransformFeedback::CaptureVertexInterleaved::s_primitive_cases_xfb[] = {
2790 GL_POINTS, GL_LINES, GL_LINES, GL_LINES, GL_TRIANGLES, GL_TRIANGLES, GL_TRIANGLES
2791 };
2792
2793 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_element_indices_counts[] = { 4, 4, 4, 4,
2794 6, 4, 4 };
2795
2796 const glw::GLuint gl3cts::TransformFeedback::CaptureVertexInterleaved::s_framebuffer_size =
2797 2; /* If you change this, update checkFramebuffer function according. */
2798
2799 const glw::GLfloat gl3cts::TransformFeedback::CaptureVertexInterleaved::s_rasterization_epsilon = 0.0625;
2800
2801 /*-----------------------------------------------------------------------------------------------*/
2802
CaptureGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)2803 gl3cts::TransformFeedback::CaptureGeometryInterleaved::CaptureGeometryInterleaved(deqp::Context& context,
2804 const char* test_name,
2805 const char* test_description)
2806 : CaptureVertexInterleaved(context, test_name, test_description)
2807 {
2808 }
2809
~CaptureGeometryInterleaved(void)2810 gl3cts::TransformFeedback::CaptureGeometryInterleaved::~CaptureGeometryInterleaved(void)
2811 {
2812 }
2813
iterate(void)2814 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureGeometryInterleaved::iterate(void)
2815 {
2816 /* Functions handler */
2817 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2818
2819 /* Initializations. */
2820 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
2821 bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)));
2822 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
2823 bool is_arb_gs_4 = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4");
2824
2825 bool is_ok = true;
2826 bool test_error = false;
2827
2828 /* Tests. */
2829 try
2830 {
2831 if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4))
2832 {
2833 fetchLimits();
2834 createFramebuffer();
2835 createTransformFeedbackBuffer();
2836 createVertexArrayObject();
2837
2838 for (glw::GLuint i_primitive_case = 0;
2839 (i_primitive_case < s_geometry_interleaved_primitive_cases_count) && is_ok; ++i_primitive_case)
2840 {
2841 buildProgram(i_primitive_case);
2842
2843 gl.useProgram(m_program);
2844
2845 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
2846
2847 for (glw::GLint i_bind_case = 0; (i_bind_case < BIND_BUFFER_CASES_COUNT) && is_ok; ++i_bind_case)
2848 {
2849 if ((i_bind_case == BIND_BUFFER_OFFSET_CASE) && (DE_NULL == m_glBindBufferOffsetEXT))
2850 {
2851 continue;
2852 }
2853
2854 bindBuffer((BindBufferCase)i_bind_case);
2855
2856 draw(i_primitive_case);
2857
2858 is_ok = is_ok && checkFramebuffer(s_primitive_cases[i_primitive_case]);
2859 is_ok = is_ok &&
2860 checkTransformFeedbackBuffer((BindBufferCase)i_bind_case,
2861 s_geometry_interleaved_primitive_cases_xfb[i_primitive_case]);
2862 }
2863
2864 gl.deleteProgram(m_program);
2865
2866 m_program = 0;
2867
2868 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
2869 }
2870 }
2871 }
2872 catch (...)
2873 {
2874 is_ok = false;
2875 test_error = true;
2876 }
2877
2878 /* Clean objects. */
2879 clean();
2880
2881 /* Result's setup. */
2882 if (is_ok)
2883 {
2884 /* Log success. */
2885 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Geometry have passed."
2886 << tcu::TestLog::EndMessage;
2887
2888 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2889 }
2890 else
2891 {
2892 if (test_error)
2893 {
2894 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
2895 }
2896 else
2897 {
2898 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2899 }
2900 }
2901
2902 return STOP;
2903 }
2904
fetchLimits(void)2905 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::fetchLimits(void)
2906 {
2907 /* Functions handler */
2908 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2909
2910 /* Fetching limits. */
2911 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_transform_feedback_components);
2912
2913 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2914
2915 if (m_max_transform_feedback_components == 0)
2916 {
2917 throw 0;
2918 }
2919
2920 glw::GLint max_geometry_total_components = 0;
2921
2922 gl.getIntegerv(GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS, &max_geometry_total_components);
2923
2924 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
2925
2926 if (max_geometry_total_components == 0)
2927 {
2928 throw 0;
2929 }
2930
2931 if (m_max_transform_feedback_components * 4 > max_geometry_total_components)
2932 {
2933 m_max_transform_feedback_components = max_geometry_total_components / 4;
2934 }
2935 }
2936
buildProgram(glw::GLuint primitive_case)2937 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::buildProgram(glw::GLuint primitive_case)
2938 {
2939 /* Functions handler */
2940 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2941
2942 /* Preparing source code. */
2943 std::string geometry_shader(s_geometry_shader_source_code_template); /* Storage for vertex shader source code. */
2944 std::string transform_feedback_variable_declarations(
2945 ""); /* String to contain all custom outputs from vertex shader. */
2946 std::string transform_feedback_variable_setters(
2947 ""); /* String containing all initializations of custom outputs from vertex shader. */
2948 std::vector<std::string> transform_feedback_varyings(m_max_transform_feedback_components); /* Varyings array. */
2949 std::vector<const glw::GLchar*> transform_feedback_varyings_c(
2950 m_max_transform_feedback_components); /* Varyings array in C form to pass to the GL. */
2951
2952 glw::GLint user_defined_transform_feedback_interleaved_varyings_count =
2953 m_max_transform_feedback_components /* total max to be written by the shader */
2954 / 4 /* components per vec4 */
2955 // / 4 /* number of vertices */
2956 - 1 /* gl_Position */;
2957
2958 glw::GLint all_transform_feedback_interleaved_varyings_count =
2959 user_defined_transform_feedback_interleaved_varyings_count + 1 /* gl_Position */;
2960
2961 /* Most of varyings is declarated output variables. */
2962 for (glw::GLint i = 0; i < user_defined_transform_feedback_interleaved_varyings_count; ++i)
2963 {
2964 /* Preparing variable name. */
2965 std::string varying = "result_";
2966 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
2967
2968 transform_feedback_varyings[i] = varying;
2969
2970 transform_feedback_varyings_c[i] = transform_feedback_varyings[i].c_str();
2971
2972 /* Preparing variable declaration. */
2973 transform_feedback_variable_declarations.append("out vec4 ");
2974 transform_feedback_variable_declarations.append(varying);
2975 transform_feedback_variable_declarations.append(";\n");
2976
2977 /* Preparing variable setters. */
2978 transform_feedback_variable_setters.append(" ");
2979 transform_feedback_variable_setters.append(varying);
2980 transform_feedback_variable_setters.append(" = vec4(");
2981 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4));
2982 transform_feedback_variable_setters.append(".0, ");
2983 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 1));
2984 transform_feedback_variable_setters.append(".0, ");
2985 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 2));
2986 transform_feedback_variable_setters.append(".0, ");
2987 transform_feedback_variable_setters.append(gl3cts::TransformFeedback::Utilities::itoa(i * 4 + 3));
2988 transform_feedback_variable_setters.append(".0);\n");
2989 }
2990
2991 /* Last four varying components are gl_Position components. */
2992 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] =
2993 "gl_Position";
2994
2995 transform_feedback_varyings_c[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */] =
2996 transform_feedback_varyings[user_defined_transform_feedback_interleaved_varyings_count /* gl_Position */]
2997 .c_str();
2998
2999 /* Preprocess vertex shader source code template. */
3000 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3001 geometry_shader, "TEMPLATE_PRIMITIVE_TYPE", s_geometry_interleaved_primitive_cases[primitive_case]);
3002 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3003 geometry_shader, "TEMPLATE_INPUT_OUTPUT_DECLARATIONS", transform_feedback_variable_declarations);
3004 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(geometry_shader, "TEMPLATE_OUTPUT_SETTERS",
3005 transform_feedback_variable_setters);
3006 geometry_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(
3007 geometry_shader, "TEMPLATE_RASTERIZATION_EPSILON",
3008 gl3cts::TransformFeedback::Utilities::ftoa(s_rasterization_epsilon));
3009
3010 /* Compile, link and check. */
3011 m_program = gl3cts::TransformFeedback::Utilities::buildProgram(
3012 gl, m_context.getTestContext().getLog(), geometry_shader.c_str(), NULL, NULL, s_blank_vertex_shader_source_code,
3013 s_fragment_shader_source_code, &transform_feedback_varyings_c[0],
3014 all_transform_feedback_interleaved_varyings_count, m_attrib_type);
3015
3016 if (0 == m_program)
3017 {
3018 throw 0;
3019 }
3020 }
3021
draw(glw::GLuint primitive_case)3022 void gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(glw::GLuint primitive_case)
3023 {
3024 /* Functions handler */
3025 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3026
3027 gl.clear(GL_COLOR_BUFFER_BIT);
3028 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
3029
3030 gl.beginTransformFeedback(s_geometry_interleaved_primitive_cases_xfb[primitive_case]);
3031 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
3032
3033 gl.drawArrays(GL_POINTS, 0, 1);
3034 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
3035
3036 gl.endTransformFeedback();
3037 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedbac call failed.");
3038 }
3039
3040 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_shader_source_code_template =
3041 "#version 150\n"
3042 "\n"
3043 "layout(points) in;\n"
3044 "layout(TEMPLATE_PRIMITIVE_TYPE, max_vertices = 4) out;\n"
3045 "\n"
3046 "TEMPLATE_INPUT_OUTPUT_DECLARATIONS"
3047 "\n"
3048 "void main()\n"
3049 "{\n"
3050 " /* Note: The points are moved 0.0625 from the borders to\n"
3051 " reduce non-XFB related rasterization problems. */\n"
3052 "\n"
3053 " gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
3054 "1.0);\n"
3055 "TEMPLATE_OUTPUT_SETTERS"
3056 " EmitVertex();\n"
3057 "\n"
3058 " gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 1.0 - TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
3059 "1.0);\n"
3060 "TEMPLATE_OUTPUT_SETTERS"
3061 " EmitVertex();\n"
3062 "\n"
3063 " gl_Position = vec4(-1.0 + TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
3064 "1.0);\n"
3065 "TEMPLATE_OUTPUT_SETTERS"
3066 " EmitVertex();\n"
3067 "\n"
3068 " gl_Position = vec4( 1.0 - TEMPLATE_RASTERIZATION_EPSILON, -1.0 + TEMPLATE_RASTERIZATION_EPSILON, 0.0, "
3069 "1.0);\n"
3070 "TEMPLATE_OUTPUT_SETTERS"
3071 " EmitVertex();\n"
3072 "}\n";
3073
3074 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_blank_vertex_shader_source_code =
3075 "#version 130\n"
3076 "\n"
3077 "void main()\n"
3078 "{\n"
3079 "}\n";
3080
3081 const glw::GLchar* gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases[] = {
3082 "points", "line_strip", "triangle_strip"
3083 };
3084
3085 const glw::GLenum gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_xfb[] =
3086 { GL_POINTS, GL_LINES, GL_TRIANGLES };
3087
3088 const glw::GLuint gl3cts::TransformFeedback::CaptureGeometryInterleaved::s_geometry_interleaved_primitive_cases_count =
3089 sizeof(s_geometry_interleaved_primitive_cases) / sizeof(s_geometry_interleaved_primitive_cases[0]);
3090
3091 /*-----------------------------------------------------------------------------------------------*/
3092
CaptureVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3093 gl3cts::TransformFeedback::CaptureVertexSeparate::CaptureVertexSeparate(deqp::Context& context, const char* test_name,
3094 const char* test_description)
3095 : CaptureVertexInterleaved(context, test_name, test_description)
3096 , m_buffers(DE_NULL)
3097 , m_max_transform_feedback_separate_attribs(0)
3098 {
3099 m_attrib_type = GL_SEPARATE_ATTRIBS;
3100 }
3101
fetchLimits(void)3102 void gl3cts::TransformFeedback::CaptureVertexSeparate::fetchLimits(void)
3103 {
3104 /* Functions handler */
3105 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3106
3107 /* Fetching limits. */
3108 glw::GLint max_transform_feedback_separate_components;
3109
3110 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &max_transform_feedback_separate_components);
3111
3112 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3113
3114 if (max_transform_feedback_separate_components < 4)
3115 {
3116 throw 0;
3117 }
3118
3119 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_transform_feedback_separate_attribs);
3120
3121 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3122
3123 if (m_max_transform_feedback_separate_attribs == 0)
3124 {
3125 throw 0;
3126 }
3127
3128 m_max_transform_feedback_components = m_max_transform_feedback_separate_attribs * 4 /* vec4 is used */;
3129
3130 glw::GLint max_varyings_components = 0;
3131
3132 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &max_varyings_components);
3133
3134 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3135
3136 if (max_varyings_components == 0)
3137 {
3138 throw 0;
3139 }
3140
3141 if (m_max_transform_feedback_components > max_varyings_components)
3142 {
3143 m_max_transform_feedback_components = max_varyings_components;
3144 }
3145 }
3146
createTransformFeedbackBuffer(void)3147 void gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer(void)
3148 {
3149 /* Functions handler */
3150 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3151
3152 m_buffers = new glw::GLuint[m_max_transform_feedback_components];
3153
3154 if (DE_NULL == m_buffers)
3155 {
3156 throw 0;
3157 }
3158
3159 gl.genBuffers(m_max_transform_feedback_separate_attribs, m_buffers);
3160 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
3161
3162 m_buffer_size = static_cast<glw::GLuint>(m_max_vertices_drawn * 4 /* vec4 */ * sizeof(glw::GLfloat));
3163
3164 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3165 {
3166 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]);
3167 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3168
3169 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffer_size, NULL, GL_DYNAMIC_READ);
3170 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
3171 }
3172 }
3173
bindBuffer(BindBufferCase bind_case)3174 void gl3cts::TransformFeedback::CaptureVertexSeparate::bindBuffer(BindBufferCase bind_case)
3175 {
3176 /* Functions handler */
3177 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3178
3179 switch (bind_case)
3180 {
3181 case BIND_BUFFER_BASE_CASE:
3182 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3183 {
3184 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i]);
3185 }
3186 break;
3187 case BIND_BUFFER_RANGE_CASE:
3188 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3189 {
3190 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0, m_buffer_size);
3191 }
3192 break;
3193 case BIND_BUFFER_OFFSET_CASE:
3194 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs; ++i)
3195 {
3196 m_glBindBufferOffsetEXT(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_buffers[i], 0);
3197 }
3198 break;
3199 default:
3200 throw 0;
3201 }
3202 }
3203
cleanBuffer(void)3204 void gl3cts::TransformFeedback::CaptureVertexSeparate::cleanBuffer(void)
3205 {
3206 /* Functions handler */
3207 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3208
3209 if (DE_NULL != m_buffers)
3210 {
3211 gl.deleteBuffers(m_max_transform_feedback_separate_attribs, m_buffers);
3212
3213 delete[] m_buffers;
3214
3215 m_buffers = DE_NULL;
3216 }
3217 }
3218
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3219 bool gl3cts::TransformFeedback::CaptureVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3220 glw::GLenum primitive_type)
3221 {
3222 /* Functions handler */
3223 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3224
3225 glw::GLuint number_of_vertices = 0;
3226
3227 switch (primitive_type)
3228 {
3229 case GL_POINTS:
3230 number_of_vertices = 4;
3231 break;
3232 case GL_LINES:
3233 number_of_vertices = 4;
3234 break;
3235 case GL_LINE_LOOP:
3236 number_of_vertices = 8;
3237 break;
3238 case GL_LINE_STRIP:
3239 number_of_vertices = 6;
3240 break;
3241 case GL_TRIANGLES:
3242 number_of_vertices = 6;
3243 break;
3244 case GL_TRIANGLE_STRIP:
3245 number_of_vertices = 6;
3246 break;
3247 case GL_TRIANGLE_FAN:
3248 number_of_vertices = 6;
3249 break;
3250 default:
3251 throw 0;
3252 }
3253
3254 bool is_ok = true;
3255
3256 for (glw::GLint i = 0; i < m_max_transform_feedback_separate_attribs - 1; ++i)
3257 {
3258 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[i]);
3259 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3260
3261 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3262 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3263
3264 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
3265 {
3266 for (glw::GLuint k = 0; k < 4 /* vec4 */; ++k)
3267 {
3268 glw::GLfloat result = results[j * 4 + k];
3269 glw::GLfloat reference = (glw::GLfloat)(i * 4 + k);
3270
3271 if (fabs(result - reference) > 0.125 /* precision */)
3272 {
3273 is_ok = false;
3274
3275 break;
3276 }
3277 }
3278 }
3279
3280 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3281 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3282 }
3283
3284 /* gl_Position */
3285 if (is_ok)
3286 {
3287 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_buffers[m_max_transform_feedback_separate_attribs - 1]);
3288 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
3289
3290 glw::GLfloat* results = (glw::GLfloat*)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
3291 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
3292
3293 for (glw::GLuint j = 0; (j < number_of_vertices) && is_ok; ++j)
3294 {
3295 glw::GLfloat result[4] = { results[j * 4], results[j * 4 + 1], results[j * 4 + 2], results[j * 4 + 3] };
3296
3297 if ((fabs(fabs(result[0]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
3298 (fabs(fabs(result[1]) - 1.0 + s_rasterization_epsilon) > 0.125 /* precision */) ||
3299 (fabs(result[2]) > 0.125 /* precision */) || (fabs(result[3] - 1.0) > 0.125 /* precision */))
3300 {
3301 is_ok = false;
3302
3303 break;
3304 }
3305 }
3306
3307 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
3308 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
3309 }
3310
3311 return is_ok;
3312 }
3313
3314 /*-----------------------------------------------------------------------------------------------*/
3315
CaptureGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3316 gl3cts::TransformFeedback::CaptureGeometrySeparate::CaptureGeometrySeparate(deqp::Context& context,
3317 const char* test_name,
3318 const char* test_description)
3319 : CaptureVertexInterleaved(context, test_name, test_description)
3320 , CaptureVertexSeparate(context, test_name, test_description)
3321 , CaptureGeometryInterleaved(context, test_name, test_description)
3322 , m_buffers(DE_NULL)
3323 , m_max_transform_feedback_separate_attribs(0)
3324 {
3325 }
3326
3327 /*-----------------------------------------------------------------------------------------------*/
3328
CheckGetXFBVarying(deqp::Context & context,const char * test_name,const char * test_description)3329 gl3cts::TransformFeedback::CheckGetXFBVarying::CheckGetXFBVarying(deqp::Context& context, const char* test_name,
3330 const char* test_description)
3331 : deqp::TestCase(context, test_name, test_description)
3332 , m_context(context)
3333 , m_max_xfb_interleaved_components(0)
3334 , m_max_xfb_separate_attributes(0)
3335 , m_max_xfb_separate_components(0)
3336 , m_max_varying_components(0)
3337 , m_max_varying_vectors(0)
3338 , m_max_geometry_total_output_components(0)
3339 {
3340 }
3341
~CheckGetXFBVarying(void)3342 gl3cts::TransformFeedback::CheckGetXFBVarying::~CheckGetXFBVarying(void)
3343 {
3344 }
3345
fetchLimits(void)3346 void gl3cts::TransformFeedback::CheckGetXFBVarying::fetchLimits(void)
3347 {
3348 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3349
3350 /* Fetching limits. */
3351 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS, &m_max_xfb_interleaved_components);
3352 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS, &m_max_xfb_separate_attributes);
3353 gl.getIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS, &m_max_xfb_separate_components);
3354 gl.getIntegerv(GL_MAX_VARYING_COMPONENTS, &m_max_varying_components);
3355 gl.getIntegerv(GL_MAX_VARYING_VECTORS, &m_max_varying_vectors);
3356 gl.getIntegerv(GL_MAX_GEOMETRY_OUTPUT_COMPONENTS, &m_max_geometry_total_output_components);
3357
3358 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
3359 }
3360
numberOfAttributes(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type)3361 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::numberOfAttributes(glw::GLuint capture_way,
3362 glw::GLuint shader_case,
3363 glw::GLuint varying_type)
3364 {
3365 /* Setup limits of the case. */
3366 const glw::GLuint max_total_components =
3367 ((s_shader_cases[shader_case].geometry_shader == DE_NULL) ? m_max_varying_components :
3368 m_max_geometry_total_output_components) -
3369 4 /* gl_Position is not captured */;
3370
3371 const glw::GLuint attribute_components = s_varying_types[varying_type].components_count;
3372 const glw::GLuint max_xfb_components = (s_capture_ways[capture_way] == GL_INTERLEAVED_ATTRIBS) ?
3373 m_max_xfb_interleaved_components :
3374 (attribute_components * m_max_xfb_separate_components);
3375
3376 if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS)
3377 {
3378 if (attribute_components > glw::GLuint(m_max_xfb_separate_components))
3379 {
3380 return 0;
3381 }
3382 }
3383
3384 /* Setup number of attributes. */
3385 glw::GLuint number_of_attributes = max_xfb_components / attribute_components;
3386
3387 if (s_capture_ways[capture_way] == GL_SEPARATE_ATTRIBS &&
3388 number_of_attributes > glw::GLuint(m_max_xfb_separate_attributes))
3389 {
3390 number_of_attributes = m_max_xfb_separate_attributes;
3391 }
3392
3393 /* Clamp to limits. */
3394 if (number_of_attributes * attribute_components > max_total_components)
3395 {
3396 number_of_attributes = max_total_components / attribute_components;
3397 }
3398
3399 /* Vectors limit. */
3400 if (attribute_components <= 4)
3401 {
3402 if (number_of_attributes > glw::GLuint(m_max_varying_vectors))
3403 {
3404 number_of_attributes = m_max_varying_vectors;
3405 }
3406 }
3407 else
3408 {
3409 if (number_of_attributes > glw::GLuint(m_max_varying_vectors) / 4)
3410 {
3411 number_of_attributes = glw::GLuint(m_max_varying_vectors) / 4;
3412 }
3413 }
3414
3415 /* Return. */
3416 return number_of_attributes;
3417 }
3418
iterate(void)3419 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CheckGetXFBVarying::iterate(void)
3420 {
3421 /* Functions handler */
3422 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3423
3424 /* Initializations. */
3425 bool is_at_least_gl_30 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 0)));
3426 bool is_at_least_gl_32 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 2)));
3427 bool is_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
3428 bool is_arb_gs_4 = m_context.getContextInfo().isExtensionSupported("GL_ARB_geometry_shader4");
3429
3430 bool is_ok = true;
3431 bool test_error = false;
3432
3433 glw::GLuint program = 0;
3434
3435 /* Tests. */
3436 try
3437 {
3438 if ((is_at_least_gl_30 || is_ext_tf_1) && (is_at_least_gl_32 || is_arb_gs_4))
3439 {
3440 fetchLimits();
3441
3442 for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i)
3443 {
3444 for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j)
3445 {
3446 for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k)
3447 {
3448 glw::GLuint n = numberOfAttributes(i, j, k);
3449
3450 if (n)
3451 {
3452 program = buildProgram(i, j, k, n);
3453
3454 is_ok = is_ok && (program != 0);
3455
3456 is_ok = is_ok && check(program, i, j, k, n);
3457
3458 gl.deleteProgram(program);
3459
3460 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
3461
3462 program = 0;
3463 }
3464 }
3465 }
3466 }
3467 }
3468 }
3469 catch (...)
3470 {
3471 is_ok = false;
3472 test_error = true;
3473
3474 if (program)
3475 {
3476 gl.deleteProgram(program);
3477
3478 program = 0;
3479 }
3480 }
3481
3482 /* Result's setup. */
3483 if (is_ok)
3484 {
3485 /* Log success. */
3486 m_context.getTestContext().getLog() << tcu::TestLog::Message
3487 << "Test checking Get Transform Feedback Varying have passed."
3488 << tcu::TestLog::EndMessage;
3489
3490 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3491 }
3492 else
3493 {
3494 if (test_error)
3495 {
3496 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3497 }
3498 else
3499 {
3500 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3501 }
3502 }
3503
3504 return STOP;
3505 }
3506
buildProgram(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type,glw::GLuint number_of_attributes)3507 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way,
3508 glw::GLuint shader_case,
3509 glw::GLuint varying_type,
3510 glw::GLuint number_of_attributes)
3511 {
3512 /* Functions handler */
3513 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3514
3515 /* Preparing source code. */
3516 std::string xfb_variable_declarations("");
3517 std::string xfb_variable_setters("");
3518 std::vector<std::string> xfb_varyings(number_of_attributes);
3519 std::vector<const glw::GLchar*> xfb_varyings_c(number_of_attributes);
3520
3521 /* Most of varyings is declarated output variables. */
3522 for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3523 {
3524 /* Varying name: result_# */
3525 std::string varying = "result_";
3526 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3527
3528 xfb_varyings[i] = varying;
3529 xfb_varyings_c[i] = xfb_varyings[i].c_str();
3530
3531 /* Varying declaration: out TYPE result_#;*/
3532 xfb_variable_declarations.append("out ");
3533 xfb_variable_declarations.append(s_varying_types[varying_type].name);
3534 xfb_variable_declarations.append(" ");
3535 xfb_variable_declarations.append(varying);
3536 xfb_variable_declarations.append(";\n");
3537
3538 /* Varying setter: result_# = TYPE(#); */
3539 xfb_variable_setters.append(" ");
3540 xfb_variable_setters.append(varying);
3541 xfb_variable_setters.append(" = ");
3542 xfb_variable_setters.append(s_varying_types[varying_type].name);
3543 xfb_variable_setters.append("(");
3544 xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i));
3545 if (s_varying_types[varying_type].float_component)
3546 {
3547 /* if varying is float varying setter is: result_# = TYPE(#.0); */
3548 xfb_variable_setters.append(".0");
3549 }
3550 xfb_variable_setters.append(");\n");
3551 }
3552
3553 /* Preprocess vertex shader source code template. */
3554 const glw::GLchar* vertex_shader = s_shader_cases[shader_case].vertex_shader;
3555 const glw::GLchar* geometry_shader = s_shader_cases[shader_case].geometry_shader;
3556
3557 std::string xfb_shader;
3558
3559 if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3560 {
3561 /* XFB tested in vertex shader. */
3562 xfb_shader = vertex_shader;
3563 }
3564 else
3565 {
3566 /* XFB tested in geometry shader. */
3567 xfb_shader = geometry_shader;
3568 }
3569
3570 /* Preprocess shader. */
3571 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS",
3572 xfb_variable_declarations);
3573 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS",
3574 xfb_variable_setters);
3575
3576 if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3577 {
3578 /* XFB tested in vertex shader. */
3579 vertex_shader = xfb_shader.c_str();
3580 }
3581 else
3582 {
3583 /* XFB tested in geometry shader. */
3584 geometry_shader = xfb_shader.c_str();
3585 }
3586
3587 /* Compile, link and check. */
3588 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
3589 gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader,
3590 &xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]);
3591
3592 /* Check compilation status. */
3593 if (0 == program)
3594 {
3595 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n"
3596 << vertex_shader << "Geometry shader:\n"
3597 << ((DE_NULL == geometry_shader) ? "" : geometry_shader)
3598 << "Fragment shader:\n"
3599 << s_generic_fragment_shader << tcu::TestLog::EndMessage;
3600
3601 throw 0;
3602 }
3603
3604 return program;
3605 }
3606
check(glw::GLuint program,glw::GLuint capture_way,glw::GLuint shader_case UNUSED,glw::GLuint varying_type,glw::GLuint number_of_attributes)3607 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way,
3608 glw::GLuint shader_case UNUSED, glw::GLuint varying_type,
3609 glw::GLuint number_of_attributes)
3610 {
3611 /* Functions handler */
3612 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3613 glw::GLuint max_length = 0;
3614
3615 /* Inspect glGetTransformFeedbackVarying. */
3616 for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3617 {
3618 const glw::GLsizei bufSize = 18;
3619 glw::GLsizei length = 0;
3620 glw::GLsizei size = 0;
3621 glw::GLenum type = GL_NONE;
3622 glw::GLchar name[18] = { 0 }; /* Size of bufSize. */
3623
3624 gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name);
3625
3626 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed.");
3627
3628 max_length = deMaxu32(max_length, glw::GLuint(length));
3629
3630 /* Check name. */
3631 if (length)
3632 {
3633 std::string varying = name;
3634 std::string varying_ref = "result_";
3635 varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3636
3637 if (0 != varying.compare(varying_ref))
3638 {
3639 return false;
3640 }
3641 }
3642 else
3643 {
3644 return false;
3645 }
3646
3647 /* Check size. */
3648 const glw::GLuint size_ref = 1;
3649
3650 if (size != size_ref)
3651 {
3652 return false;
3653 }
3654
3655 /* Check type. */
3656 if (type != s_varying_types[varying_type].type)
3657 {
3658 return false;
3659 }
3660 }
3661
3662 /* Inspect glGetProgramiv. */
3663 glw::GLint xfb_varyings = 0;
3664 glw::GLint xfb_mode = 0;
3665 glw::GLint xfb_varying_max_length = 0;
3666
3667 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings);
3668 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode);
3669 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length);
3670
3671 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
3672
3673 if (glw::GLuint(xfb_varyings) != number_of_attributes)
3674 {
3675 return false;
3676 }
3677
3678 if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way])
3679 {
3680 return false;
3681 }
3682
3683 if (glw::GLuint(xfb_varying_max_length) < max_length)
3684 {
3685 return false;
3686 }
3687
3688 return true;
3689 }
3690
3691 const glw::GLchar* gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n"
3692 "\n"
3693 "out vec4 color;\n"
3694 "\n"
3695 "void main()\n"
3696 "{\n"
3697 " color = vec4(1.0);\n"
3698 "}\n";
3699
3700 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase
3701 gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = { { /* Vertex Shader. */
3702 "#version 130\n"
3703 "\n"
3704 "TEMPLATE_OUTPUT_DECLARATIONS"
3705 "\n"
3706 "void main()\n"
3707 "{\n"
3708 " gl_Position = vec4(1.0);\n"
3709 "TEMPLATE_OUTPUT_SETTERS"
3710 "}\n",
3711
3712 /* Geometry Shader. */
3713 NULL },
3714 { /* Vertex Shader. */
3715 "#version 130\n"
3716 "\n"
3717 "void main()\n"
3718 "{\n"
3719 "}\n",
3720
3721 /* Geometry Shader. */
3722 "#version 150\n"
3723 "\n"
3724 "layout(points) in;\n"
3725 "layout(points, max_vertices = 1) out;\n"
3726 "\n"
3727 "TEMPLATE_OUTPUT_DECLARATIONS"
3728 "\n"
3729 "void main()\n"
3730 "{\n"
3731 " gl_Position = vec4(1.0);\n"
3732 "TEMPLATE_OUTPUT_SETTERS"
3733 " EmitVertex();\n"
3734 "}\n" } };
3735
3736 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count =
3737 sizeof(s_shader_cases) / sizeof(s_shader_cases[0]);
3738
3739 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType
3740 gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = {
3741 /* type, name, #components, is component float */
3742 { GL_FLOAT, "float", 1, true },
3743 { GL_FLOAT_VEC2, "vec2", 2, true },
3744 { GL_FLOAT_VEC3, "vec3", 3, true },
3745 { GL_FLOAT_VEC4, "vec4", 4, true },
3746 { GL_INT, "int", 1, false },
3747 { GL_INT_VEC2, "ivec2", 2, false },
3748 { GL_INT_VEC3, "ivec3", 3, false },
3749 { GL_INT_VEC4, "ivec4", 4, false },
3750 { GL_UNSIGNED_INT, "uint", 1, false },
3751 { GL_UNSIGNED_INT_VEC2, "uvec2", 2, false },
3752 { GL_UNSIGNED_INT_VEC3, "uvec3", 3, false },
3753 { GL_UNSIGNED_INT_VEC4, "uvec4", 4, false },
3754 { GL_FLOAT_MAT2, "mat2", 4, true },
3755 { GL_FLOAT_MAT3, "mat3", 9, true },
3756 { GL_FLOAT_MAT4, "mat4", 16, true }
3757 };
3758
3759 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count =
3760 sizeof(s_varying_types) / sizeof(s_varying_types[0]);
3761
3762 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = { GL_INTERLEAVED_ATTRIBS,
3763 GL_SEPARATE_ATTRIBS };
3764
3765 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count =
3766 sizeof(s_capture_ways) / sizeof(s_capture_ways[0]);
3767
3768 /*-----------------------------------------------------------------------------------------------*/
3769
QueryVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3770 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context& context, const char* test_name,
3771 const char* test_description)
3772 : CaptureVertexInterleaved(context, test_name, test_description), m_query_object(0)
3773 {
3774 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3775 }
3776
createTransformFeedbackBuffer(void)3777 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void)
3778 {
3779 /* Functions handler */
3780 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3781
3782 /* Create buffer object. */
3783 gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer();
3784
3785 /* Create query object. */
3786 gl.genQueries(1, &m_query_object);
3787 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3788 }
3789
draw(glw::GLuint primitive_case)3790 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case)
3791 {
3792 /* Functions handler */
3793 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3794
3795 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3796 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3797
3798 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
3799
3800 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3801 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3802 }
3803
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3804 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3805 glw::GLenum primitive_type)
3806 {
3807 /* Functions handler */
3808 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3809
3810 glw::GLuint number_of_primitives;
3811
3812 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3813 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3814
3815 /* expected result */
3816 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3817
3818 if (number_of_primitives_reference != number_of_primitives)
3819 {
3820 return false;
3821 }
3822
3823 return true;
3824 }
3825
clean(void)3826 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void)
3827 {
3828 /* Functions handler */
3829 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3830
3831 /* Delete query object. */
3832 gl.deleteQueries(1, &m_query_object);
3833 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3834
3835 /* Other */
3836 gl3cts::TransformFeedback::CaptureVertexInterleaved::clean();
3837 }
3838
3839 /*-----------------------------------------------------------------------------------------------*/
3840
QueryGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3841 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context& context,
3842 const char* test_name,
3843 const char* test_description)
3844 : CaptureVertexInterleaved(context, test_name, test_description)
3845 , CaptureGeometryInterleaved(context, test_name, test_description)
3846 {
3847 m_query_object = 0;
3848 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3849 }
3850
createTransformFeedbackBuffer(void)3851 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void)
3852 {
3853 /* Functions handler */
3854 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3855
3856 /* Create buffer object. */
3857 gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer();
3858
3859 /* Create query object. */
3860 gl.genQueries(1, &m_query_object);
3861 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3862 }
3863
draw(glw::GLuint primitive_case)3864 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case)
3865 {
3866 /* Functions handler */
3867 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3868
3869 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3870 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3871
3872 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
3873
3874 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3875 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3876 }
3877
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3878 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3879 glw::GLenum primitive_type)
3880 {
3881 /* Functions handler */
3882 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3883
3884 glw::GLuint number_of_primitives;
3885
3886 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3887 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3888
3889 /* expected result */
3890 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3891
3892 if (number_of_primitives_reference != number_of_primitives)
3893 {
3894 return false;
3895 }
3896
3897 return true;
3898 }
3899
clean(void)3900 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void)
3901 {
3902 /* Functions handler */
3903 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3904
3905 /* Delete query object. */
3906 gl.deleteQueries(1, &m_query_object);
3907 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3908
3909 /* Other. */
3910 gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean();
3911 }
3912
3913 /*-----------------------------------------------------------------------------------------------*/
3914
QueryVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3915 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context& context, const char* test_name,
3916 const char* test_description)
3917 : CaptureVertexInterleaved(context, test_name, test_description)
3918 , CaptureVertexSeparate(context, test_name, test_description)
3919 {
3920 m_query_object = 0;
3921 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3922 }
3923
createTransformFeedbackBuffer(void)3924 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void)
3925 {
3926 /* Functions handler */
3927 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3928
3929 /* Create buffer object. */
3930 gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer();
3931
3932 /* Create query object. */
3933 gl.genQueries(1, &m_query_object);
3934 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3935 }
3936
draw(glw::GLuint primitive_case)3937 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case)
3938 {
3939 /* Functions handler */
3940 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3941
3942 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3943 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3944
3945 gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case);
3946
3947 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3948 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3949 }
3950
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3951 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3952 glw::GLenum primitive_type)
3953 {
3954 /* Functions handler */
3955 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3956
3957 glw::GLuint number_of_primitives;
3958
3959 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3960 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3961
3962 /* expected result */
3963 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3964
3965 if (number_of_primitives_reference != number_of_primitives)
3966 {
3967 return false;
3968 }
3969
3970 return true;
3971 }
3972
clean(void)3973 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void)
3974 {
3975 /* Functions handler */
3976 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3977
3978 /* Delete query object. */
3979 gl.deleteQueries(1, &m_query_object);
3980 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3981
3982 /* Other */
3983 gl3cts::TransformFeedback::CaptureVertexSeparate::clean();
3984 }
3985
3986 /*-----------------------------------------------------------------------------------------------*/
3987
QueryGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3988 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context& context, const char* test_name,
3989 const char* test_description)
3990 : CaptureVertexInterleaved(context, test_name, test_description)
3991 , CaptureVertexSeparate(context, test_name, test_description)
3992 , CaptureGeometrySeparate(context, test_name, test_description)
3993 {
3994 m_query_object = 0;
3995 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3996 }
3997
createTransformFeedbackBuffer(void)3998 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void)
3999 {
4000 /* Functions handler */
4001 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4002
4003 /* Create buffer object. */
4004 gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer();
4005
4006 /* Create query object. */
4007 gl.genQueries(1, &m_query_object);
4008 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
4009 }
4010
draw(glw::GLuint primitive_case)4011 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case)
4012 {
4013 /* Functions handler */
4014 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4015
4016 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
4017 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
4018
4019 gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case);
4020
4021 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4022 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
4023 }
4024
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)4025 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
4026 glw::GLenum primitive_type)
4027 {
4028 /* Functions handler */
4029 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4030
4031 glw::GLuint number_of_primitives;
4032
4033 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
4034 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
4035
4036 /* expected result */
4037 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
4038
4039 if (number_of_primitives_reference != number_of_primitives)
4040 {
4041 return false;
4042 }
4043
4044 return true;
4045 }
4046
clean(void)4047 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void)
4048 {
4049 /* Functions handler */
4050 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4051
4052 /* Delete query object. */
4053 gl.deleteQueries(1, &m_query_object);
4054 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
4055
4056 /* Other */
4057 gl3cts::TransformFeedback::CaptureGeometrySeparate::clean();
4058 }
4059
4060 /*-----------------------------------------------------------------------------------------------*/
4061
DiscardVertex(deqp::Context & context,const char * test_name,const char * test_description)4062 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context& context, const char* test_name,
4063 const char* test_description)
4064 : CaptureVertexInterleaved(context, test_name, test_description)
4065 {
4066 }
4067
draw(glw::GLuint primitive_case)4068 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case)
4069 {
4070 /* Functions handler */
4071 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4072
4073 /* Must clear before rasterizer discard */
4074 gl.clear(GL_COLOR_BUFFER_BIT);
4075 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4076
4077 gl.enable(GL_RASTERIZER_DISCARD);
4078 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4079
4080 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
4081
4082 gl.disable(GL_RASTERIZER_DISCARD);
4083 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4084 }
4085
checkFramebuffer(glw::GLuint primitive_case UNUSED)4086 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4087 {
4088 /* Functions handler */
4089 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4090
4091 /* Fetch framebuffer. */
4092 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4093
4094 if (s_framebuffer_size > 0)
4095 {
4096 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4097 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4098 }
4099
4100 /* Check results.
4101 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4102 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4103 {
4104 if (fabs(*i) > 0.0625f /* precision */)
4105 {
4106 return false;
4107 }
4108 }
4109
4110 return true;
4111 }
4112
4113 /*-----------------------------------------------------------------------------------------------*/
4114
DiscardGeometry(deqp::Context & context,const char * test_name,const char * test_description)4115 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context& context, const char* test_name,
4116 const char* test_description)
4117 : CaptureVertexInterleaved(context, test_name, test_description)
4118 , CaptureGeometryInterleaved(context, test_name, test_description)
4119 {
4120 }
4121
draw(glw::GLuint primitive_case)4122 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case)
4123 {
4124 /* Functions handler */
4125 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4126
4127 /* Must clear before rasterizer discard */
4128 gl.clear(GL_COLOR_BUFFER_BIT);
4129 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4130
4131 gl.enable(GL_RASTERIZER_DISCARD);
4132 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4133
4134 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
4135
4136 gl.disable(GL_RASTERIZER_DISCARD);
4137 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4138 }
4139
checkFramebuffer(glw::GLuint primitive_case UNUSED)4140 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4141 {
4142 /* Functions handler */
4143 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4144
4145 /* Fetch framebuffer. */
4146 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4147
4148 if (s_framebuffer_size > 0)
4149 {
4150 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4151 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4152 }
4153
4154 /* Check results.
4155 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4156 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4157 {
4158 if (fabs(*i) > 0.0625f /* precision */)
4159 {
4160 return false;
4161 }
4162 }
4163
4164 return true;
4165 }
4166
4167 /*-----------------------------------------------------------------------------------------------*/
4168
DrawXFB(deqp::Context & context,const char * test_name,const char * test_description)4169 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context& context, const char* test_name, const char* test_description)
4170 : deqp::TestCase(context, test_name, test_description)
4171 , m_context(context)
4172 , m_program_id_xfb(0)
4173 , m_program_id_draw(0)
4174 , m_fbo_id(0)
4175 , m_rbo_id(0)
4176 , m_vao_id(0)
4177 {
4178 memset(m_xfb_id, 0, sizeof(m_xfb_id));
4179 memset(m_bo_id, 0, sizeof(m_bo_id));
4180 }
4181
~DrawXFB(void)4182 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void)
4183 {
4184 }
4185
iterate(void)4186 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void)
4187 {
4188 /* Initializations. */
4189 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4190 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4191
4192 bool is_ok = true;
4193 bool test_error = false;
4194
4195 /* Tests. */
4196 try
4197 {
4198 if (is_at_least_gl_40 || is_arb_tf_2)
4199 {
4200 for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i)
4201 {
4202 prepare(s_capture_modes[i]);
4203
4204 bindVAO(m_vao_id);
4205 useProgram(m_program_id_xfb);
4206
4207 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4208 {
4209 bindXFB(m_xfb_id[j]);
4210 bindBOForXFB(s_capture_modes[i], m_bo_id[j]);
4211 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4212 useGeometrySet(m_program_id_xfb, false);
4213 drawForCapture(true, true, false, false);
4214
4215 is_ok = is_ok && inspectXFBState(true, true);
4216 }
4217
4218 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4219 {
4220 bindXFB(m_xfb_id[j]);
4221 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4222 useGeometrySet(m_program_id_xfb, true);
4223 drawForCapture(false, false, true, true);
4224
4225 is_ok = is_ok && inspectXFBState(false, false);
4226 }
4227
4228 useProgram(m_program_id_draw);
4229
4230 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4231 {
4232 bindXFB(m_xfb_id[j]);
4233 bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]);
4234 drawToFramebuffer(m_xfb_id[j]);
4235
4236 is_ok =
4237 is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4238 }
4239
4240 clean();
4241 }
4242 }
4243 }
4244 catch (...)
4245 {
4246 is_ok = false;
4247 test_error = true;
4248 clean();
4249 }
4250
4251 /* Result's setup. */
4252 if (is_ok)
4253 {
4254 /* Log success. */
4255 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have passed."
4256 << tcu::TestLog::EndMessage;
4257
4258 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4259 }
4260 else
4261 {
4262 if (test_error)
4263 {
4264 /* Log error. */
4265 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have approached error."
4266 << tcu::TestLog::EndMessage;
4267
4268 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4269 }
4270 else
4271 {
4272 /* Log fail. */
4273 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have failed."
4274 << tcu::TestLog::EndMessage;
4275
4276 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4277 }
4278 }
4279
4280 return STOP;
4281 }
4282
prepare(glw::GLenum capture_mode)4283 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode)
4284 {
4285 /* Functions handler */
4286 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4287
4288 /* Prepare programs. */
4289 m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram(
4290 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader,
4291 s_xfb_varyings, s_xfb_varyings_count, capture_mode);
4292
4293 if (0 == m_program_id_xfb)
4294 {
4295 throw 0;
4296 }
4297
4298 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(),
4299 NULL, NULL, NULL, s_vertex_shader_draw,
4300 s_fragment_shader, NULL, 0, capture_mode);
4301
4302 if (0 == m_program_id_draw)
4303 {
4304 throw 0;
4305 }
4306
4307 /* Prepare transform feedbacks. */
4308 gl.genTransformFeedbacks(s_xfb_count, m_xfb_id);
4309 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4310
4311 /* Prepare buffer objects. */
4312 gl.genBuffers(s_xfb_count, m_bo_id);
4313 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4314
4315 for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4316 {
4317 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
4318 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4319
4320 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY);
4321 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4322 }
4323
4324 /* Prepare framebuffer. */
4325 gl.clearColor(0.f, 0.f, 0.f, 1.f);
4326 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4327
4328 gl.genFramebuffers(1, &m_fbo_id);
4329 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
4330
4331 gl.genRenderbuffers(1, &m_rbo_id);
4332 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
4333
4334 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4335 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
4336
4337 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
4338 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
4339
4340 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size);
4341 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
4342
4343 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
4344 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
4345
4346 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
4347 {
4348 throw 0;
4349 }
4350
4351 gl.viewport(0, 0, s_view_size, s_view_size);
4352 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
4353
4354 /* Create empty Vertex Array Object */
4355 gl.genVertexArrays(1, &m_vao_id);
4356 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4357 }
4358
bindXFB(glw::GLuint xfb_id)4359 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id)
4360 {
4361 /* Functions handler */
4362 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4363
4364 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id);
4365 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
4366 }
4367
bindVAO(glw::GLuint vao_id)4368 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id)
4369 {
4370 /* Functions handler */
4371 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4372
4373 gl.bindVertexArray(vao_id);
4374 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4375 }
4376
bindBOForXFB(glw::GLenum capture_mode,glw::GLuint bo_id)4377 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id)
4378 {
4379 /* Functions handler */
4380 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4381
4382 switch (capture_mode)
4383 {
4384 case GL_INTERLEAVED_ATTRIBS:
4385 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
4386 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4387 break;
4388 case GL_SEPARATE_ATTRIBS:
4389 for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i)
4390 {
4391 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count,
4392 (i + 1) * s_capture_size / s_xfb_varyings_count);
4393 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4394 }
4395 break;
4396 default:
4397 throw 0;
4398 }
4399 }
4400
bindBOForDraw(glw::GLuint program_id,glw::GLenum capture_mode,glw::GLuint bo_id)4401 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode,
4402 glw::GLuint bo_id)
4403 {
4404 /* Functions handler */
4405 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4406
4407 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
4408
4409 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4410
4411 glw::GLuint position_location = gl.getAttribLocation(program_id, "position");
4412 glw::GLuint color_location = gl.getAttribLocation(program_id, "color");
4413
4414 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4415
4416 glw::GLvoid* color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4417 (glw::GLvoid*)(4 /* components */ * sizeof(glw::GLfloat)) :
4418 (glw::GLvoid*)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat));
4419
4420 glw::GLuint stride =
4421 static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4422 (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) :
4423 (4 /* components */ * sizeof(glw::GLfloat)));
4424
4425 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL);
4426 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset);
4427
4428 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4429
4430 gl.enableVertexAttribArray(position_location);
4431 gl.enableVertexAttribArray(color_location);
4432
4433 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4434 }
4435
useProgram(glw::GLuint program_id)4436 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id)
4437 {
4438 /* Functions handler */
4439 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4440
4441 gl.useProgram(program_id);
4442 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4443 }
4444
useColour(glw::GLuint program_id,glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4445 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g,
4446 glw::GLfloat b, glw::GLfloat a)
4447 {
4448 /* Functions handler */
4449 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4450
4451 glw::GLint location = gl.getUniformLocation(program_id, "color");
4452 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4453
4454 gl.uniform4f(location, r, g, b, a);
4455 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4456 }
4457
useGeometrySet(glw::GLuint program_id,bool invert_sign)4458 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign)
4459 {
4460 /* Functions handler */
4461 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4462
4463 glw::GLint location = gl.getUniformLocation(program_id, "invert_sign");
4464 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4465
4466 gl.uniform1f(location, invert_sign ? -1.f : 1.f);
4467 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4468 }
4469
clean()4470 void gl3cts::TransformFeedback::DrawXFB::clean()
4471 {
4472 /* Functions handler */
4473 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4474
4475 gl.useProgram(0);
4476
4477 if (m_program_id_xfb)
4478 {
4479 gl.deleteProgram(m_program_id_xfb);
4480
4481 m_program_id_xfb = 0;
4482 }
4483
4484 if (m_program_id_draw)
4485 {
4486 gl.deleteProgram(m_program_id_draw);
4487
4488 m_program_id_draw = 1;
4489 }
4490
4491 for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4492 {
4493 if (m_xfb_id[i])
4494 {
4495 gl.deleteTransformFeedbacks(1, &m_xfb_id[i]);
4496
4497 m_xfb_id[i] = 0;
4498 }
4499 }
4500
4501 for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4502 {
4503 if (m_bo_id[i])
4504 {
4505 gl.deleteBuffers(1, &m_bo_id[i]);
4506
4507 m_bo_id[i] = 0;
4508 }
4509 }
4510
4511 if (m_vao_id)
4512 {
4513 gl.deleteVertexArrays(1, &m_vao_id);
4514
4515 m_vao_id = 0;
4516 }
4517
4518 if (m_fbo_id)
4519 {
4520 gl.deleteFramebuffers(1, &m_fbo_id);
4521
4522 m_fbo_id = 0;
4523 }
4524
4525 if (m_rbo_id)
4526 {
4527 gl.deleteRenderbuffers(1, &m_rbo_id);
4528
4529 m_rbo_id = 0;
4530 }
4531 }
4532
drawForCapture(bool begin_xfb,bool pause_xfb,bool resume_xfb,bool end_xfb)4533 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb)
4534 {
4535 /* Functions handler */
4536 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4537
4538 gl.enable(GL_RASTERIZER_DISCARD);
4539 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4540
4541 if (begin_xfb)
4542 {
4543 gl.beginTransformFeedback(GL_POINTS);
4544 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4545 }
4546
4547 if (resume_xfb)
4548 {
4549 gl.resumeTransformFeedback();
4550 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed.");
4551 }
4552
4553 gl.drawArrays(GL_POINTS, 0, 3);
4554
4555 if (pause_xfb)
4556 {
4557 gl.pauseTransformFeedback();
4558 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
4559 }
4560
4561 if (end_xfb)
4562 {
4563 gl.endTransformFeedback();
4564 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4565 }
4566
4567 gl.disable(GL_RASTERIZER_DISCARD);
4568 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4569 }
4570
drawToFramebuffer(glw::GLuint xfb_id)4571 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id)
4572 {
4573 /* Functions handler */
4574 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4575
4576 gl.clearColor(0.f, 0.f, 0.f, 0.f);
4577 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4578
4579 gl.clear(GL_COLOR_BUFFER_BIT);
4580 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4581
4582 gl.drawTransformFeedback(GL_TRIANGLES, xfb_id);
4583 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4584 }
4585
checkFramebuffer(glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4586 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b,
4587 glw::GLfloat a)
4588 {
4589 /* Functions handler */
4590 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4591
4592 /* Number of pixels. */
4593 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
4594
4595 /* Fetch framebuffer. */
4596 std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */);
4597
4598 if (s_view_size > 0)
4599 {
4600 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
4601 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4602 }
4603
4604 /* Convert color to integer. */
4605 glw::GLubyte ir = (glw::GLubyte)(255.f * r);
4606 glw::GLubyte ig = (glw::GLubyte)(255.f * g);
4607 glw::GLubyte ib = (glw::GLubyte)(255.f * b);
4608 glw::GLubyte ia = (glw::GLubyte)(255.f * a);
4609
4610 /* Check results. */
4611 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
4612 {
4613 if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) ||
4614 (pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia))
4615 {
4616 return false;
4617 }
4618 }
4619
4620 return true;
4621 }
4622
inspectXFBState(bool shall_be_paused,bool shall_be_active)4623 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active)
4624 {
4625 /* Functions handler */
4626 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4627
4628 glw::GLint is_paused = 0;
4629 glw::GLint is_active = 0;
4630
4631 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused);
4632 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active);
4633
4634 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4635
4636 if ((is_paused == -1) || (is_active == -1))
4637 {
4638 throw 0;
4639 }
4640
4641 if (shall_be_paused ^ (is_paused == GL_TRUE))
4642 {
4643 return false;
4644 }
4645
4646 if (shall_be_active ^ (is_active == GL_TRUE))
4647 {
4648 return false;
4649 }
4650
4651 return true;
4652 }
4653
4654 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb =
4655 "#version 130\n"
4656 "\n"
4657 "uniform vec4 color;\n"
4658 "uniform float invert_sign;\n"
4659 "out vec4 colour;\n"
4660 "\n"
4661 "void main()\n"
4662 "{\n"
4663 " switch(gl_VertexID)\n"
4664 " {\n"
4665 " case 0:\n"
4666 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
4667 " break;\n"
4668 " case 1:\n"
4669 " gl_Position = vec4(-1.0 * invert_sign, 1.0, 0.0, 1.0);\n"
4670 " break;\n"
4671 " case 2:\n"
4672 " gl_Position = vec4( 1.0, 1.0 * invert_sign, 0.0, 1.0);\n"
4673 " break;\n"
4674 " }\n"
4675 "\n"
4676 " colour = color;\n"
4677 "}\n";
4678
4679 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n"
4680 "\n"
4681 "in vec4 color;\n"
4682 "in vec4 position;\n"
4683 "out vec4 colour;\n"
4684 "\n"
4685 "void main()\n"
4686 "{\n"
4687 " gl_Position = position;\n"
4688 " colour = color;\n"
4689 "}\n";
4690
4691 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n"
4692 "\n"
4693 "in vec4 colour;\n"
4694 "out vec4 pixel;\n"
4695 "\n"
4696 "void main()\n"
4697 "{\n"
4698 " pixel = colour;\n"
4699 "}\n";
4700
4701 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = { "gl_Position",
4702 "colour" };
4703
4704 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = { GL_INTERLEAVED_ATTRIBS,
4705 GL_SEPARATE_ATTRIBS };
4706 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count =
4707 sizeof(s_capture_modes) / sizeof(s_capture_modes[0]);
4708
4709 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = { { 1.f, 0.f, 0.f, 1.f },
4710 { 0.f, 1.f, 0.f, 1.f },
4711 { 0.f, 0.f, 1.f, 1.f } };
4712
4713 /*-----------------------------------------------------------------------------------------------*/
4714
DrawXFBFeedback(deqp::Context & context,const char * test_name,const char * test_description)4715 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context& context, const char* test_name,
4716 const char* test_description)
4717 : deqp::TestCase(context, test_name, test_description)
4718 , m_context(context)
4719 , m_program_id(0)
4720 , m_xfb_id(0)
4721 , m_source_bo_index(0)
4722 {
4723 memset(m_bo_id, 1, sizeof(m_bo_id));
4724 memset(m_bo_id, 1, sizeof(m_vao_id));
4725 }
4726
~DrawXFBFeedback(void)4727 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void)
4728 {
4729 }
4730
iterate(void)4731 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void)
4732 {
4733 /* Initializations. */
4734 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4735 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4736
4737 bool is_ok = true;
4738 bool test_error = false;
4739
4740 /* Tests. */
4741 try
4742 {
4743 if (is_at_least_gl_40 || is_arb_tf_2)
4744 {
4745 prepareAndBind();
4746 draw(true);
4747 swapBuffers();
4748 draw(false);
4749 swapBuffers();
4750 draw(false);
4751
4752 is_ok = is_ok && check();
4753 }
4754 }
4755 catch (...)
4756 {
4757 is_ok = false;
4758 test_error = true;
4759 }
4760
4761 /* Clean GL objects. */
4762 clean();
4763
4764 /* Result's setup. */
4765 if (is_ok)
4766 {
4767 /* Log success. */
4768 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have passed."
4769 << tcu::TestLog::EndMessage;
4770
4771 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4772 }
4773 else
4774 {
4775 if (test_error)
4776 {
4777 /* Log error. */
4778 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have approached error."
4779 << tcu::TestLog::EndMessage;
4780
4781 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4782 }
4783 else
4784 {
4785 /* Log fail. */
4786 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have failed."
4787 << tcu::TestLog::EndMessage;
4788
4789 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4790 }
4791 }
4792
4793 return STOP;
4794 }
4795
prepareAndBind()4796 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind()
4797 {
4798 /* Functions handler */
4799 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4800
4801 /* Prepare programs. */
4802 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL,
4803 NULL, NULL, s_vertex_shader, s_fragment_shader,
4804 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
4805
4806 if (0 == m_program_id)
4807 {
4808 throw 0;
4809 }
4810
4811 gl.useProgram(m_program_id);
4812 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4813
4814 /* Prepare transform feedbacks. */
4815 gl.genTransformFeedbacks(1, &m_xfb_id);
4816 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4817
4818 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
4819 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
4820
4821 /* Prepare buffer objects. */
4822 gl.genBuffers(s_bo_count, m_bo_id);
4823 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4824
4825 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]);
4826 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4827
4828 gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY);
4829 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4830
4831 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]);
4832 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4833
4834 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
4835 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4836
4837 /* Setup vertex arrays. */
4838 gl.genVertexArrays(s_bo_count, m_vao_id);
4839 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4840
4841 glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position");
4842 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4843
4844 for (glw::GLuint i = 0; i < 2; ++i)
4845 {
4846 gl.bindVertexArray(m_vao_id[i]);
4847 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4848
4849 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]);
4850 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4851
4852 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4853 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4854
4855 gl.enableVertexAttribArray(position_location);
4856 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4857 }
4858
4859 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
4860 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4861
4862 gl.bindVertexArray(m_vao_id[0]);
4863 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4864 }
4865
swapBuffers()4866 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers()
4867 {
4868 /* Functions handler */
4869 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4870
4871 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]);
4872 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4873
4874 m_source_bo_index = (m_source_bo_index + 1) % 2;
4875
4876 gl.bindVertexArray(m_vao_id[(m_source_bo_index)]);
4877 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4878 }
4879
draw(bool is_first_draw)4880 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw)
4881 {
4882 /* Functions handler */
4883 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4884
4885 gl.enable(GL_RASTERIZER_DISCARD);
4886 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4887
4888 gl.beginTransformFeedback(GL_POINTS);
4889 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4890
4891 if (is_first_draw)
4892 {
4893 gl.drawArrays(GL_POINTS, 0, 1);
4894 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
4895 }
4896 else
4897 {
4898 gl.drawTransformFeedback(GL_POINTS, m_xfb_id);
4899 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4900 }
4901
4902 gl.endTransformFeedback();
4903 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4904
4905 gl.disable(GL_RASTERIZER_DISCARD);
4906 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4907 }
4908
check()4909 bool gl3cts::TransformFeedback::DrawXFBFeedback::check()
4910 {
4911 /* Functions handler */
4912 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4913
4914 glw::GLfloat* results =
4915 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
4916 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
4917
4918 bool is_ok = false;
4919
4920 if (results)
4921 {
4922 if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f))
4923 {
4924 is_ok = true;
4925 }
4926
4927 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4928 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
4929 }
4930
4931 return is_ok;
4932 }
4933
clean()4934 void gl3cts::TransformFeedback::DrawXFBFeedback::clean()
4935 {
4936 /* Functions handler */
4937 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4938
4939 gl.useProgram(0);
4940
4941 if (m_program_id)
4942 {
4943 gl.deleteProgram(m_program_id);
4944
4945 m_program_id = 0;
4946 }
4947
4948 if (m_xfb_id)
4949 {
4950 gl.deleteTransformFeedbacks(1, &m_xfb_id);
4951
4952 m_xfb_id = 0;
4953 }
4954
4955 for (glw::GLuint i = 0; i < s_bo_count; ++i)
4956 {
4957 if (m_bo_id[i])
4958 {
4959 gl.deleteBuffers(1, &m_bo_id[i]);
4960
4961 m_bo_id[i] = 0;
4962 }
4963 }
4964
4965 for (glw::GLuint i = 0; i < s_bo_count; ++i)
4966 {
4967 if (m_vao_id[i])
4968 {
4969 gl.deleteVertexArrays(1, &m_vao_id[i]);
4970
4971 m_vao_id[i] = 0;
4972 }
4973 }
4974 }
4975
4976 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n"
4977 "\n"
4978 "in vec4 position;\n"
4979 "\n"
4980 "void main()\n"
4981 "{\n"
4982 " gl_Position = position * 2.0;\n"
4983 "}\n";
4984
4985 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n"
4986 "\n"
4987 "out vec4 pixel;\n"
4988 "\n"
4989 "void main()\n"
4990 "{\n"
4991 " pixel = vec4(1.0);\n"
4992 "}\n";
4993
4994 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position";
4995
4996 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position";
4997
4998 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = { 1.f, 2.f, 3.f, 4.f };
4999
5000 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count =
5001 sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */;
5002
5003 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data);
5004
5005 /*-----------------------------------------------------------------------------------------------*/
5006
CaptureSpecialInterleaved(deqp::Context & context,const char * test_name,const char * test_description)5007 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context& context,
5008 const char* test_name,
5009 const char* test_description)
5010 : deqp::TestCase(context, test_name, test_description)
5011 , m_context(context)
5012 , m_program_id(0)
5013 , m_vao_id(0)
5014 , m_xfb_id(0)
5015 {
5016 memset(m_bo_id, 0, sizeof(m_bo_id));
5017 }
5018
~CaptureSpecialInterleaved(void)5019 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void)
5020 {
5021 }
5022
iterate(void)5023 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void)
5024 {
5025 /* Initializations. */
5026 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5027 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5028
5029 bool is_ok = true;
5030 bool test_error = false;
5031
5032 /* Tests. */
5033 try
5034 {
5035 if (is_at_least_gl_40 || is_arb_tf_3)
5036 {
5037 prepareAndBind();
5038 draw();
5039
5040 is_ok = is_ok && check();
5041 }
5042 }
5043 catch (...)
5044 {
5045 is_ok = false;
5046 test_error = true;
5047 }
5048
5049 /* Clean GL objects. */
5050 clean();
5051
5052 /* Result's setup. */
5053 if (is_ok)
5054 {
5055 /* Log success. */
5056 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have passed."
5057 << tcu::TestLog::EndMessage;
5058
5059 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5060 }
5061 else
5062 {
5063 if (test_error)
5064 {
5065 /* Log error. */
5066 m_context.getTestContext().getLog() << tcu::TestLog::Message
5067 << "Capture Special Interleaved have approached error."
5068 << tcu::TestLog::EndMessage;
5069
5070 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5071 }
5072 else
5073 {
5074 /* Log fail. */
5075 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have failed."
5076 << tcu::TestLog::EndMessage;
5077
5078 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5079 }
5080 }
5081
5082 return STOP;
5083 }
5084
prepareAndBind()5085 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind()
5086 {
5087 /* Functions handler */
5088 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5089
5090 /* Prepare programs. */
5091 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(
5092 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings,
5093 s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5094
5095 if (0 == m_program_id)
5096 {
5097 throw 0;
5098 }
5099
5100 gl.useProgram(m_program_id);
5101 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5102
5103 /* Prepare transform feedbacks. */
5104 gl.genTransformFeedbacks(1, &m_xfb_id);
5105 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5106
5107 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5108 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5109
5110 /* Create empty Vertex Array Object */
5111 gl.genVertexArrays(1, &m_vao_id);
5112 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5113
5114 gl.bindVertexArray(m_vao_id);
5115 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5116
5117 /* Prepare buffer objects. */
5118 gl.genBuffers(s_bo_ids_count, m_bo_id);
5119 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5120
5121 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5122 {
5123 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5124 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5125
5126 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5127 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5128
5129 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5130 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5131 }
5132 }
5133
draw()5134 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw()
5135 {
5136 /* Functions handler */
5137 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5138
5139 gl.enable(GL_RASTERIZER_DISCARD);
5140 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5141
5142 gl.beginTransformFeedback(GL_POINTS);
5143 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5144
5145 gl.drawArrays(GL_POINTS, 0, 1);
5146 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5147
5148 gl.endTransformFeedback();
5149 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5150
5151 gl.disable(GL_RASTERIZER_DISCARD);
5152 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5153 }
5154
check()5155 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check()
5156 {
5157 /* Functions handler */
5158 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5159
5160 bool is_ok = true;
5161
5162 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]);
5163 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5164
5165 glw::GLfloat* results =
5166 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5167 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5168
5169 if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) ||
5170 /* gl_SkipComponents4 here */
5171 (results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0))
5172 {
5173 is_ok = false;
5174 }
5175
5176 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5177 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5178
5179 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]);
5180 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5181
5182 results = (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5183 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5184
5185 if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) ||
5186 /* gl_SkipComponents4 here */
5187 (results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0))
5188 {
5189 is_ok = false;
5190 }
5191
5192 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5193 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5194
5195 return is_ok;
5196 }
5197
clean()5198 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean()
5199 {
5200 /* Functions handler */
5201 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5202
5203 gl.useProgram(0);
5204
5205 if (m_program_id)
5206 {
5207 gl.deleteProgram(m_program_id);
5208
5209 m_program_id = 0;
5210 }
5211
5212 if (m_xfb_id)
5213 {
5214 gl.deleteTransformFeedbacks(1, &m_xfb_id);
5215
5216 m_xfb_id = 0;
5217 }
5218
5219 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5220 {
5221 if (m_bo_id[i])
5222 {
5223 gl.deleteBuffers(1, &m_bo_id[i]);
5224
5225 m_bo_id[i] = 0;
5226 }
5227 }
5228
5229 if (m_vao_id)
5230 {
5231 gl.deleteVertexArrays(1, &m_vao_id);
5232
5233 m_vao_id = 0;
5234 }
5235 }
5236
5237 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader =
5238 "#version 130\n"
5239 "\n"
5240 "out vec4 variable_1;\n"
5241 "out vec4 variable_2;\n"
5242 "out vec4 variable_3;\n"
5243 "out vec4 variable_4;\n"
5244 "\n"
5245 "void main()\n"
5246 "{\n"
5247 " variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n"
5248 " variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n"
5249 " variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n"
5250 " variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n"
5251 "\n"
5252 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5253 "}\n";
5254
5255 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n"
5256 "\n"
5257 "out vec4 pixel;\n"
5258 "\n"
5259 "void main()\n"
5260 "{\n"
5261 " pixel = vec4(1.0);\n"
5262 "}\n";
5263
5264 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] =
5265 { "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer",
5266 "variable_3", "gl_SkipComponents4", "variable_4" };
5267
5268 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count =
5269 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5270
5271 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size =
5272 3 /*number of variables / empty places */ * 4 /* vec4 */
5273 * sizeof(glw::GLfloat);
5274
5275 /*-----------------------------------------------------------------------------------------------*/
5276
DrawXFBStream(deqp::Context & context,const char * test_name,const char * test_description)5277 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context& context, const char* test_name,
5278 const char* test_description)
5279 : deqp::TestCase(context, test_name, test_description)
5280 , m_context(context)
5281 , m_program_id_generate(0)
5282 , m_program_id_draw(0)
5283 , m_vao_id(0)
5284 , m_xfb_id(0)
5285 , m_fbo_id(0)
5286 , m_rbo_id(0)
5287 {
5288 memset(m_bo_id, 0, sizeof(m_bo_id));
5289 memset(m_qo_id, 0, sizeof(m_qo_id));
5290 }
5291
~DrawXFBStream(void)5292 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void)
5293 {
5294 }
5295
iterate(void)5296 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void)
5297 {
5298 /* Functions handler */
5299 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5300
5301 /* Initializations. */
5302 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5303 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5304 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
5305
5306 glw::GLint max_vertex_streams = 0;
5307
5308 bool is_ok = true;
5309 bool test_error = false;
5310
5311 /* Tests. */
5312 try
5313 {
5314 if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5))
5315 {
5316 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
5317 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5318
5319 if (max_vertex_streams >= 2)
5320 {
5321 prepareObjects();
5322
5323 useProgram(m_program_id_generate);
5324
5325 drawForXFB();
5326
5327 is_ok = is_ok && inspectQueries();
5328
5329 useProgram(m_program_id_draw);
5330
5331 setupVertexArray(m_bo_id[0]);
5332
5333 drawForFramebuffer(0);
5334
5335 setupVertexArray(m_bo_id[1]);
5336
5337 drawForFramebuffer(1);
5338
5339 is_ok = is_ok && check();
5340 }
5341 }
5342 }
5343 catch (...)
5344 {
5345 is_ok = false;
5346 test_error = true;
5347 }
5348
5349 /* Clean GL objects. */
5350 clean();
5351
5352 /* Result's setup. */
5353 if (is_ok)
5354 {
5355 /* Log success. */
5356 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have passed."
5357 << tcu::TestLog::EndMessage;
5358
5359 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5360 }
5361 else
5362 {
5363 if (test_error)
5364 {
5365 /* Log error. */
5366 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have approached error."
5367 << tcu::TestLog::EndMessage;
5368
5369 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5370 }
5371 else
5372 {
5373 /* Log fail. */
5374 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have failed."
5375 << tcu::TestLog::EndMessage;
5376
5377 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5378 }
5379 }
5380
5381 return STOP;
5382 }
5383
prepareObjects()5384 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects()
5385 {
5386 /* Functions handler */
5387 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5388
5389 /* Prepare programs. */
5390 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5391 gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank,
5392 s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5393
5394 if (0 == m_program_id_generate)
5395 {
5396 throw 0;
5397 }
5398
5399 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5400 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0,
5401 GL_INTERLEAVED_ATTRIBS);
5402
5403 if (0 == m_program_id_draw)
5404 {
5405 throw 0;
5406 }
5407
5408 /* Prepare transform feedbacks. */
5409 gl.genTransformFeedbacks(1, &m_xfb_id);
5410 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5411
5412 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5413 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5414
5415 /* Create empty Vertex Array Object */
5416 gl.genVertexArrays(1, &m_vao_id);
5417 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5418
5419 gl.bindVertexArray(m_vao_id);
5420 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5421
5422 /* Prepare buffer objects. */
5423 gl.genBuffers(s_bo_ids_count, m_bo_id);
5424 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5425
5426 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5427 {
5428 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5429 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5430
5431 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5432 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5433
5434 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5435 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5436 }
5437
5438 /* Generate queries */
5439 gl.genQueries(s_qo_ids_count, m_qo_id);
5440 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
5441
5442 /* Prepare framebuffer. */
5443 gl.clearColor(0.f, 0.f, 0.f, 1.f);
5444 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5445
5446 gl.genFramebuffers(1, &m_fbo_id);
5447 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5448
5449 gl.genRenderbuffers(1, &m_rbo_id);
5450 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5451
5452 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5453 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5454
5455 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5456 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5457
5458 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5459 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5460
5461 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5462 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5463
5464 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5465 {
5466 throw 0;
5467 }
5468
5469 gl.viewport(0, 0, s_view_size, s_view_size);
5470 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5471 }
5472
setupVertexArray(glw::GLuint bo_id)5473 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id)
5474 {
5475 /* Functions handler */
5476 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5477
5478 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
5479 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5480
5481 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5482 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5483
5484 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5485 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5486
5487 gl.enableVertexAttribArray(position_location);
5488 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5489 }
5490
useProgram(glw::GLuint program_id)5491 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id)
5492 {
5493 /* Functions handler */
5494 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5495
5496 gl.useProgram(program_id);
5497 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5498 }
5499
drawForXFB()5500 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB()
5501 {
5502 /* Functions handler */
5503 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5504
5505 gl.enable(GL_RASTERIZER_DISCARD);
5506 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5507
5508 gl.beginTransformFeedback(GL_POINTS);
5509 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5510
5511 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]);
5512 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5513
5514 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]);
5515 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5516
5517 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]);
5518 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5519
5520 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]);
5521 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5522
5523 gl.drawArrays(GL_POINTS, 0, 1);
5524 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5525
5526 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0);
5527 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5528
5529 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1);
5530 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5531
5532 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
5533 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5534
5535 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1);
5536 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5537
5538 gl.endTransformFeedback();
5539 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5540
5541 gl.disable(GL_RASTERIZER_DISCARD);
5542 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5543 }
5544
drawForFramebuffer(glw::GLuint stream)5545 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream)
5546 {
5547 /* Functions handler */
5548 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5549
5550 gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream);
5551 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed.");
5552 }
5553
inspectQueries()5554 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries()
5555 {
5556 /* Functions handler */
5557 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5558
5559 glw::GLint generated_primitives_to_stream_0 = 0;
5560 glw::GLint generated_primitives_to_stream_1 = 0;
5561
5562 gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0);
5563 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5564
5565 gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1);
5566 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5567
5568 glw::GLint primitives_written_to_xfb_to_stream_0 = 0;
5569 glw::GLint primitives_written_to_xfb_to_stream_1 = 0;
5570
5571 gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0);
5572 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5573
5574 gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1);
5575 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5576
5577 if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) &&
5578 (primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3))
5579 {
5580 return true;
5581 }
5582
5583 return false;
5584 }
5585
check()5586 bool gl3cts::TransformFeedback::DrawXFBStream::check()
5587 {
5588 /* Functions handler */
5589 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5590
5591 /* Number of pixels. */
5592 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5593
5594 /* Fetch framebuffer. */
5595 std::vector<glw::GLfloat> pixels(number_of_pixels);
5596
5597 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
5598 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
5599
5600 /* Check results. */
5601 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
5602 {
5603 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
5604 {
5605 return false;
5606 }
5607 }
5608
5609 return true;
5610 }
5611
clean()5612 void gl3cts::TransformFeedback::DrawXFBStream::clean()
5613 {
5614 /* Functions handler */
5615 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5616
5617 gl.useProgram(0);
5618
5619 if (m_program_id_generate)
5620 {
5621 gl.deleteProgram(m_program_id_generate);
5622
5623 m_program_id_generate = 0;
5624 }
5625
5626 if (m_program_id_draw)
5627 {
5628 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5629
5630 gl.disableVertexAttribArray(position_location);
5631
5632 gl.deleteProgram(m_program_id_draw);
5633
5634 m_program_id_draw = 0;
5635 }
5636
5637 if (m_xfb_id)
5638 {
5639 gl.deleteTransformFeedbacks(1, &m_xfb_id);
5640
5641 m_xfb_id = 0;
5642 }
5643
5644 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5645 {
5646 if (m_bo_id[i])
5647 {
5648 gl.deleteBuffers(1, &m_bo_id[i]);
5649
5650 m_bo_id[i] = 0;
5651 }
5652 }
5653
5654 if (m_vao_id)
5655 {
5656 gl.deleteVertexArrays(1, &m_vao_id);
5657
5658 m_vao_id = 0;
5659 }
5660
5661 if (m_fbo_id)
5662 {
5663 gl.deleteFramebuffers(1, &m_fbo_id);
5664
5665 m_fbo_id = 0;
5666 }
5667
5668 if (m_rbo_id)
5669 {
5670 gl.deleteRenderbuffers(1, &m_rbo_id);
5671
5672 m_rbo_id = 0;
5673 }
5674 }
5675
5676 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n"
5677 "\n"
5678 "void main()\n"
5679 "{\n"
5680 "}\n";
5681
5682 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n"
5683 "\n"
5684 "in vec4 position;\n"
5685 "\n"
5686 "void main()\n"
5687 "{\n"
5688 " gl_Position = position;\n"
5689 "}\n";
5690
5691 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader =
5692 "#version 400\n"
5693 "\n"
5694 "layout(points) in;\n"
5695 "layout(points, max_vertices = 6) out;\n"
5696 "\n"
5697 "layout(stream = 1) out vec4 position;\n"
5698 "\n"
5699 "void main()\n"
5700 "{\n"
5701 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5702 " EmitStreamVertex(0);\n"
5703 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5704 " EmitStreamVertex(0);\n"
5705 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
5706 " EmitStreamVertex(0);\n"
5707 "\n"
5708 " position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5709 " EmitStreamVertex(1);\n"
5710 " position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
5711 " EmitStreamVertex(1);\n"
5712 " position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
5713 " EmitStreamVertex(1);\n"
5714 "}\n";
5715
5716 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n"
5717 "\n"
5718 "out vec4 pixel;\n"
5719 "\n"
5720 "void main()\n"
5721 "{\n"
5722 " pixel = vec4(1.0);\n"
5723 "}\n";
5724
5725 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = { "gl_Position", "gl_NextBuffer",
5726 "position" };
5727
5728 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count =
5729 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5730
5731 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size =
5732 3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat);
5733
5734 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2;
5735
5736 /*-----------------------------------------------------------------------------------------------*/
5737
DrawXFBInstanced(deqp::Context & context,const char * test_name,const char * test_description)5738 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context& context, const char* test_name,
5739 const char* test_description)
5740 : deqp::TestCase(context, test_name, test_description)
5741 , m_context(context)
5742 , m_program_id_generate(0)
5743 , m_program_id_draw(0)
5744 , m_vao_id(0)
5745 , m_xfb_id(0)
5746 , m_bo_id_xfb(0)
5747 , m_bo_id_uniform(0)
5748 , m_fbo_id(0)
5749 , m_rbo_id(0)
5750 , m_glGetUniformBlockIndex(DE_NULL)
5751 , m_glUniformBlockBinding(DE_NULL)
5752 {
5753 }
5754
~DrawXFBInstanced(void)5755 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void)
5756 {
5757 }
5758
iterate(void)5759 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void)
5760 {
5761 /* Initializations. */
5762 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
5763 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
5764 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
5765 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
5766
5767 bool is_ok = true;
5768 bool test_error = false;
5769
5770 if (is_arb_ubo)
5771 {
5772 m_glGetUniformBlockIndex =
5773 (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
5774
5775 m_glUniformBlockBinding =
5776 (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
5777
5778 if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
5779 {
5780 throw 0;
5781 }
5782 }
5783
5784 try
5785 {
5786 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced))
5787 {
5788 prepareObjects();
5789 drawForXFB();
5790 drawInstanced();
5791
5792 is_ok = is_ok && check();
5793 }
5794 }
5795 catch (...)
5796 {
5797 is_ok = false;
5798 test_error = true;
5799 }
5800
5801 /* Clean GL objects */
5802 clean();
5803
5804 /* Result's setup. */
5805 if (is_ok)
5806 {
5807 /* Log success. */
5808 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have passed."
5809 << tcu::TestLog::EndMessage;
5810
5811 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5812 }
5813 else
5814 {
5815 if (test_error)
5816 {
5817 /* Log error. */
5818 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have approached error."
5819 << tcu::TestLog::EndMessage;
5820
5821 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5822 }
5823 else
5824 {
5825 /* Log fail. */
5826 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have failed."
5827 << tcu::TestLog::EndMessage;
5828
5829 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5830 }
5831 }
5832
5833 return STOP;
5834 }
5835
prepareObjects()5836 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects()
5837 {
5838 /* Functions handler */
5839 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5840
5841 /* Prepare programs. */
5842 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5843 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader,
5844 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
5845
5846 if (0 == m_program_id_generate)
5847 {
5848 throw 0;
5849 }
5850
5851 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5852 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0,
5853 GL_INTERLEAVED_ATTRIBS);
5854
5855 if (0 == m_program_id_draw)
5856 {
5857 throw 0;
5858 }
5859
5860 /* Prepare transform feedbacks. */
5861 gl.genTransformFeedbacks(1, &m_xfb_id);
5862 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5863
5864 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5865 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5866
5867 /* Create empty Vertex Array Object */
5868 gl.genVertexArrays(1, &m_vao_id);
5869 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5870
5871 gl.bindVertexArray(m_vao_id);
5872 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5873
5874 /* Prepare xfb buffer object. */
5875 gl.genBuffers(1, &m_bo_id_xfb);
5876 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5877
5878 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb);
5879 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5880
5881 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5882 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5883
5884 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb);
5885 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5886
5887 /* Prepare uniform buffer object. */
5888 gl.genBuffers(1, &m_bo_id_uniform);
5889 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5890
5891 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
5892 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5893
5894 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
5895 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5896
5897 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
5898 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5899
5900 glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
5901 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
5902
5903 if (GL_INVALID_INDEX == uniform_index)
5904 {
5905 throw 0;
5906 }
5907
5908 m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
5909 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
5910
5911 /* Prepare framebuffer. */
5912 gl.clearColor(0.f, 0.f, 0.f, 1.f);
5913 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5914
5915 gl.genFramebuffers(1, &m_fbo_id);
5916 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5917
5918 gl.genRenderbuffers(1, &m_rbo_id);
5919 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5920
5921 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5922 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5923
5924 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5925 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5926
5927 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5928 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5929
5930 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5931 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5932
5933 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5934 {
5935 throw 0;
5936 }
5937
5938 gl.viewport(0, 0, s_view_size, s_view_size);
5939 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5940 }
5941
drawForXFB()5942 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB()
5943 {
5944 /* Functions handler */
5945 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5946
5947 gl.useProgram(m_program_id_generate);
5948 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5949
5950 gl.enable(GL_RASTERIZER_DISCARD);
5951 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5952
5953 gl.beginTransformFeedback(GL_POINTS);
5954 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5955
5956 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
5957 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5958
5959 gl.endTransformFeedback();
5960 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5961
5962 gl.disable(GL_RASTERIZER_DISCARD);
5963 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5964 }
5965
drawInstanced()5966 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced()
5967 {
5968 /* Functions handler */
5969 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5970
5971 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb);
5972 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5973
5974 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5975 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5976
5977 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5978 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5979
5980 gl.enableVertexAttribArray(position_location);
5981 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5982
5983 gl.clear(GL_COLOR_BUFFER_BIT);
5984 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
5985
5986 gl.useProgram(m_program_id_draw);
5987 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5988
5989 gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4);
5990 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5991 }
5992
check()5993 bool gl3cts::TransformFeedback::DrawXFBInstanced::check()
5994 {
5995 /* Functions handler */
5996 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5997
5998 /* Number of pixels. */
5999 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6000
6001 /* Fetch framebuffer. */
6002 std::vector<glw::GLfloat> pixels(number_of_pixels);
6003
6004 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6005 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6006
6007 /* Check results. */
6008 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6009 {
6010 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6011 {
6012 return false;
6013 }
6014 }
6015
6016 return true;
6017 }
6018
clean()6019 void gl3cts::TransformFeedback::DrawXFBInstanced::clean()
6020 {
6021 /* Functions handler */
6022 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6023
6024 gl.useProgram(0);
6025
6026 if (m_program_id_generate)
6027 {
6028 gl.deleteProgram(m_program_id_generate);
6029
6030 m_program_id_generate = 0;
6031 }
6032
6033 if (m_program_id_draw)
6034 {
6035 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6036
6037 gl.disableVertexAttribArray(position_location);
6038
6039 gl.deleteProgram(m_program_id_draw);
6040
6041 m_program_id_draw = 0;
6042 }
6043
6044 if (m_xfb_id)
6045 {
6046 gl.deleteTransformFeedbacks(1, &m_xfb_id);
6047
6048 m_xfb_id = 0;
6049 }
6050
6051 if (m_bo_id_xfb)
6052 {
6053 gl.deleteBuffers(1, &m_bo_id_xfb);
6054
6055 m_bo_id_xfb = 0;
6056 }
6057
6058 if (m_bo_id_uniform)
6059 {
6060 gl.deleteBuffers(1, &m_bo_id_uniform);
6061
6062 m_bo_id_uniform = 0;
6063 }
6064
6065 if (m_vao_id)
6066 {
6067 gl.deleteVertexArrays(1, &m_vao_id);
6068
6069 m_vao_id = 0;
6070 }
6071
6072 if (m_fbo_id)
6073 {
6074 gl.deleteFramebuffers(1, &m_fbo_id);
6075
6076 m_fbo_id = 0;
6077 }
6078
6079 if (m_rbo_id)
6080 {
6081 gl.deleteRenderbuffers(1, &m_rbo_id);
6082
6083 m_rbo_id = 0;
6084 }
6085 }
6086
6087 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate =
6088 "#version 140\n"
6089 "\n"
6090 "void main()\n"
6091 "{\n"
6092 " switch(gl_VertexID % 4)\n"
6093 " {\n"
6094 " case 0:\n"
6095 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6096 " break;\n"
6097 " case 1:\n"
6098 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6099 " break;\n"
6100 " case 2:\n"
6101 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
6102 " break;\n"
6103 " case 3:\n"
6104 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
6105 " break;\n"
6106 " }\n"
6107 "}\n";
6108
6109 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw =
6110 "#version 140\n"
6111 "\n"
6112 "uniform MatrixBlock\n"
6113 "{\n"
6114 " mat4 transformation_0;\n"
6115 " mat4 transformation_1;\n"
6116 " mat4 transformation_2;\n"
6117 " mat4 transformation_3;\n"
6118 "};\n"
6119 "\n"
6120 "in vec4 position;\n"
6121 "\n"
6122 "void main()\n"
6123 "{\n"
6124 " switch(gl_InstanceID % 4)\n"
6125 " {\n"
6126 " case 0:\n"
6127 " gl_Position = position * transformation_0;\n"
6128 " break;\n"
6129 " case 1:\n"
6130 " gl_Position = position * transformation_1;\n"
6131 " break;\n"
6132 " case 2:\n"
6133 " gl_Position = position * transformation_2;\n"
6134 " break;\n"
6135 " case 3:\n"
6136 " gl_Position = position * transformation_3;\n"
6137 " break;\n"
6138 " }\n"
6139 "}\n";
6140
6141 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n"
6142 "\n"
6143 "out vec4 pixel;\n"
6144 "\n"
6145 "void main()\n"
6146 "{\n"
6147 " pixel = vec4(1.0);\n"
6148 "}\n";
6149
6150 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position";
6151
6152 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock";
6153
6154 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size =
6155 4 /* vertex count */ * 4 /* vec4 components */
6156 * sizeof(glw::GLfloat) /* data type size */;
6157
6158 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = {
6159 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6160
6161 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6162
6163 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6164
6165 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
6166 };
6167
6168 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6169
6170 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4;
6171
6172 /*-----------------------------------------------------------------------------------------------*/
6173
DrawXFBStreamInstanced(deqp::Context & context,const char * test_name,const char * test_description)6174 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context& context, const char* test_name,
6175 const char* test_description)
6176 : deqp::TestCase(context, test_name, test_description)
6177 , m_context(context)
6178 , m_program_id_generate(0)
6179 , m_program_id_draw(0)
6180 , m_vao_id(0)
6181 , m_xfb_id(0)
6182 , m_bo_id_xfb_position(0)
6183 , m_bo_id_xfb_color(0)
6184 , m_bo_id_uniform(0)
6185 , m_fbo_id(0)
6186 , m_rbo_id(0)
6187 , m_glGetUniformBlockIndex(DE_NULL)
6188 , m_glUniformBlockBinding(DE_NULL)
6189 {
6190 }
6191
~DrawXFBStreamInstanced(void)6192 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void)
6193 {
6194 }
6195
iterate(void)6196 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void)
6197 {
6198 /* Initializations. */
6199 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
6200 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
6201 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
6202 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
6203 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
6204 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
6205
6206 bool is_ok = true;
6207 bool test_error = false;
6208
6209 if (is_arb_ubo)
6210 {
6211 m_glGetUniformBlockIndex =
6212 (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
6213
6214 m_glUniformBlockBinding =
6215 (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
6216
6217 if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
6218 {
6219 throw 0;
6220 }
6221 }
6222
6223 /* Test. */
6224 try
6225 {
6226 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) ||
6227 (is_at_least_gl_40 && is_arb_tf_instanced))
6228 {
6229 prepareObjects();
6230 drawForXFB();
6231 drawStreamInstanced();
6232
6233 is_ok = is_ok && check();
6234 }
6235 }
6236 catch (...)
6237 {
6238 is_ok = false;
6239 test_error = true;
6240 }
6241
6242 /* Clean GL objects */
6243 clean();
6244
6245 /* Result's setup. */
6246 if (is_ok)
6247 {
6248 /* Log success. */
6249 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed."
6250 << tcu::TestLog::EndMessage;
6251
6252 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6253 }
6254 else
6255 {
6256 if (test_error)
6257 {
6258 /* Log error. */
6259 m_context.getTestContext().getLog() << tcu::TestLog::Message
6260 << "Draw XFB Stream Instanced have approached error."
6261 << tcu::TestLog::EndMessage;
6262
6263 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
6264 }
6265 else
6266 {
6267 /* Log fail. */
6268 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed."
6269 << tcu::TestLog::EndMessage;
6270
6271 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6272 }
6273 }
6274
6275 return STOP;
6276 }
6277
prepareObjects()6278 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects()
6279 {
6280 /* Functions handler */
6281 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6282
6283 /* Prepare programs. */
6284 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
6285 gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank,
6286 s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
6287
6288 if (0 == m_program_id_generate)
6289 {
6290 throw 0;
6291 }
6292
6293 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
6294 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL,
6295 0, GL_INTERLEAVED_ATTRIBS);
6296
6297 if (0 == m_program_id_draw)
6298 {
6299 throw 0;
6300 }
6301
6302 /* Prepare transform feedbacks. */
6303 gl.genTransformFeedbacks(1, &m_xfb_id);
6304 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
6305
6306 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
6307 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
6308
6309 /* Create empty Vertex Array Object */
6310 gl.genVertexArrays(1, &m_vao_id);
6311 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
6312
6313 gl.bindVertexArray(m_vao_id);
6314 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
6315
6316 /* Prepare xfb buffer objects. */
6317 gl.genBuffers(1, &m_bo_id_xfb_position);
6318 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6319
6320 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position);
6321 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6322
6323 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6324 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6325
6326 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position);
6327 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6328
6329 gl.genBuffers(1, &m_bo_id_xfb_color);
6330 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6331
6332 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color);
6333 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6334
6335 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6336 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6337
6338 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color);
6339 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6340
6341 /* Prepare uniform buffer object. */
6342 gl.genBuffers(1, &m_bo_id_uniform);
6343 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6344
6345 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
6346 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6347
6348 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
6349 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6350
6351 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
6352 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6353
6354 glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
6355 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
6356
6357 if (GL_INVALID_INDEX == uniform_index)
6358 {
6359 throw 0;
6360 }
6361
6362 m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
6363 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
6364
6365 /* Prepare framebuffer. */
6366 gl.clearColor(0.f, 0.f, 0.f, 1.f);
6367 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
6368
6369 gl.genFramebuffers(1, &m_fbo_id);
6370 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
6371
6372 gl.genRenderbuffers(1, &m_rbo_id);
6373 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
6374
6375 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
6376 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
6377
6378 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
6379 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
6380
6381 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
6382 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
6383
6384 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
6385 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
6386
6387 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
6388 {
6389 throw 0;
6390 }
6391
6392 gl.viewport(0, 0, s_view_size, s_view_size);
6393 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
6394 }
6395
drawForXFB()6396 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB()
6397 {
6398 /* Functions handler */
6399 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6400
6401 gl.useProgram(m_program_id_generate);
6402 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6403
6404 gl.enable(GL_RASTERIZER_DISCARD);
6405 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
6406
6407 gl.beginTransformFeedback(GL_POINTS);
6408 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
6409
6410 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
6411 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6412
6413 gl.endTransformFeedback();
6414 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
6415
6416 gl.disable(GL_RASTERIZER_DISCARD);
6417 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
6418 }
6419
drawStreamInstanced()6420 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced()
6421 {
6422 /* Functions handler */
6423 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6424
6425 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position);
6426 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6427
6428 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6429 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6430
6431 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6432 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6433
6434 gl.enableVertexAttribArray(position_location);
6435 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6436
6437 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color);
6438 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6439
6440 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6441 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6442
6443 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6444 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6445
6446 gl.enableVertexAttribArray(color_location);
6447 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6448
6449 gl.useProgram(m_program_id_draw);
6450 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6451
6452 gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4);
6453 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6454 }
6455
check()6456 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check()
6457 {
6458 /* Functions handler */
6459 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6460
6461 /* Number of pixels. */
6462 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6463
6464 /* Fetch framebuffer. */
6465 std::vector<glw::GLfloat> pixels(number_of_pixels);
6466
6467 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6468 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6469
6470 /* Check results. */
6471 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6472 {
6473 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6474 {
6475 return false;
6476 }
6477 }
6478
6479 return true;
6480 }
6481
clean()6482 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean()
6483 {
6484 /* Functions handler */
6485 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6486
6487 gl.useProgram(0);
6488
6489 if (m_program_id_generate)
6490 {
6491 gl.deleteProgram(m_program_id_generate);
6492
6493 m_program_id_generate = 0;
6494 }
6495
6496 if (m_program_id_draw)
6497 {
6498 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6499
6500 gl.disableVertexAttribArray(position_location);
6501
6502 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6503
6504 gl.disableVertexAttribArray(color_location);
6505
6506 gl.deleteProgram(m_program_id_draw);
6507
6508 m_program_id_draw = 0;
6509 }
6510
6511 if (m_xfb_id)
6512 {
6513 gl.deleteTransformFeedbacks(1, &m_xfb_id);
6514
6515 m_xfb_id = 0;
6516 }
6517
6518 if (m_bo_id_xfb_position)
6519 {
6520 gl.deleteBuffers(1, &m_bo_id_xfb_position);
6521
6522 m_bo_id_xfb_position = 0;
6523 }
6524
6525 if (m_bo_id_xfb_color)
6526 {
6527 gl.deleteBuffers(1, &m_bo_id_xfb_color);
6528
6529 m_bo_id_xfb_position = 0;
6530 }
6531
6532 if (m_bo_id_uniform)
6533 {
6534 gl.deleteBuffers(1, &m_bo_id_uniform);
6535
6536 m_bo_id_uniform = 0;
6537 }
6538
6539 if (m_vao_id)
6540 {
6541 gl.deleteVertexArrays(1, &m_vao_id);
6542
6543 m_vao_id = 0;
6544 }
6545
6546 if (m_fbo_id)
6547 {
6548 gl.deleteFramebuffers(1, &m_fbo_id);
6549
6550 m_fbo_id = 0;
6551 }
6552
6553 if (m_rbo_id)
6554 {
6555 gl.deleteRenderbuffers(1, &m_rbo_id);
6556
6557 m_rbo_id = 0;
6558 }
6559 }
6560
6561 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n"
6562 "\n"
6563 "void main()\n"
6564 "{\n"
6565 "}\n";
6566
6567 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate =
6568 "#version 400\n"
6569 "\n"
6570 "layout(points) in;\n"
6571 "layout(points, max_vertices = 8) out;\n"
6572 "\n"
6573 "layout(stream = 1) out vec4 color;\n"
6574 "\n"
6575 "void main()\n"
6576 "{\n"
6577 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6578 " EmitStreamVertex(0);\n"
6579 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6580 " EmitStreamVertex(0);\n"
6581 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
6582 " EmitStreamVertex(0);\n"
6583 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
6584 " EmitStreamVertex(0);\n"
6585 "\n"
6586 " color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6587 " EmitStreamVertex(1);\n"
6588 " color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6589 " EmitStreamVertex(1);\n"
6590 " color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6591 " EmitStreamVertex(1);\n"
6592 " color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6593 " EmitStreamVertex(1);\n"
6594 "}\n";
6595
6596 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw =
6597 "#version 140\n"
6598 "\n"
6599 "uniform MatrixBlock\n"
6600 "{\n"
6601 " mat4 transformation_0;\n"
6602 " mat4 transformation_1;\n"
6603 " mat4 transformation_2;\n"
6604 " mat4 transformation_3;\n"
6605 "};\n"
6606 "\n"
6607 "in vec4 position;\n"
6608 "in vec4 color;\n"
6609 "out vec4 colour;\n"
6610 "\n"
6611 "void main()\n"
6612 "{\n"
6613 " switch(gl_InstanceID % 4)\n"
6614 " {\n"
6615 " case 0:\n"
6616 " gl_Position = position * transformation_0;\n"
6617 " break;\n"
6618 " case 1:\n"
6619 " gl_Position = position * transformation_1;\n"
6620 " break;\n"
6621 " case 2:\n"
6622 " gl_Position = position * transformation_2;\n"
6623 " break;\n"
6624 " case 3:\n"
6625 " gl_Position = position * transformation_3;\n"
6626 " break;\n"
6627 " }\n"
6628 " colour = color;\n"
6629 "}\n";
6630
6631 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank =
6632 "#version 130\n"
6633 "\n"
6634 "out vec4 pixel;\n"
6635 "\n"
6636 "void main()\n"
6637 "{\n"
6638 " pixel = vec4(1.0);\n"
6639 "}\n";
6640
6641 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n"
6642 "\n"
6643 "in vec4 colour;\n"
6644 "out vec4 pixel;\n"
6645 "\n"
6646 "void main()\n"
6647 "{\n"
6648 " pixel = colour;\n"
6649 "}\n";
6650
6651 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = { "gl_Position",
6652 "gl_NextBuffer", "color" };
6653
6654 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count =
6655 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
6656
6657 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock";
6658
6659 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size =
6660 4 /* vertex count */ * 4 /* vec4 components */
6661 * sizeof(glw::GLfloat) /* data type size */;
6662
6663 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = {
6664 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6665
6666 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6667
6668 0.5f, 0.0f, 0.0f, -0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
6669
6670 0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.5f, 0.0f, -0.5f, 0.0f, 0.0f, 0.5f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f
6671 };
6672
6673 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6674
6675 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4;
6676
6677 /*-----------------------------------------------------------------------------------------------*/
6678
buildProgram(glw::Functions const & gl,tcu::TestLog & log,glw::GLchar const * const geometry_shader_source,glw::GLchar const * const tessellation_control_shader_source,glw::GLchar const * const tessellation_evaluation_shader_source,glw::GLchar const * const vertex_shader_source,glw::GLchar const * const fragment_shader_source,glw::GLchar const * const * const transform_feedback_varyings,glw::GLsizei const transform_feedback_varyings_count,glw::GLenum const transform_feedback_varyings_mode,bool const do_not_detach,glw::GLint * linking_status)6679 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram(
6680 glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source,
6681 glw::GLchar const* const tessellation_control_shader_source,
6682 glw::GLchar const* const tessellation_evaluation_shader_source, glw::GLchar const* const vertex_shader_source,
6683 glw::GLchar const* const fragment_shader_source, glw::GLchar const* const* const transform_feedback_varyings,
6684 glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode,
6685 bool const do_not_detach, glw::GLint* linking_status)
6686 {
6687 glw::GLuint program = 0;
6688
6689 struct Shader
6690 {
6691 glw::GLchar const* const source;
6692 glw::GLenum const type;
6693 glw::GLuint id;
6694 } shader[] = { { geometry_shader_source, GL_GEOMETRY_SHADER, 0 },
6695 { tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0 },
6696 { tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0 },
6697 { vertex_shader_source, GL_VERTEX_SHADER, 0 },
6698 { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
6699
6700 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
6701
6702 try
6703 {
6704 /* Create program. */
6705 program = gl.createProgram();
6706 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
6707
6708 /* Shader compilation. */
6709
6710 for (glw::GLuint i = 0; i < shader_count; ++i)
6711 {
6712 if (DE_NULL != shader[i].source)
6713 {
6714 shader[i].id = gl.createShader(shader[i].type);
6715
6716 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
6717
6718 gl.attachShader(program, shader[i].id);
6719
6720 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
6721
6722 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
6723
6724 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
6725
6726 gl.compileShader(shader[i].id);
6727
6728 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
6729
6730 glw::GLint status = GL_FALSE;
6731
6732 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
6733 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6734
6735 if (GL_FALSE == status)
6736 {
6737 glw::GLint log_size = 0;
6738 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
6739 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6740
6741 glw::GLchar* log_text = new glw::GLchar[log_size];
6742
6743 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
6744
6745 log << tcu::TestLog::Message << "Shader compilation has failed.\n"
6746 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
6747 << "Shader compilation error log:\n"
6748 << log_text << "\n"
6749 << "Shader source code:\n"
6750 << shader[i].source << "\n"
6751 << tcu::TestLog::EndMessage;
6752
6753 delete[] log_text;
6754
6755 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
6756
6757 throw 0;
6758 }
6759 }
6760 }
6761
6762 /* Link. */
6763 if (transform_feedback_varyings_count)
6764 {
6765 gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings,
6766 transform_feedback_varyings_mode);
6767 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6768 }
6769
6770 gl.linkProgram(program);
6771
6772 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6773
6774 glw::GLint status = GL_FALSE;
6775
6776 gl.getProgramiv(program, GL_LINK_STATUS, &status);
6777
6778 if (DE_NULL != linking_status)
6779 {
6780 *linking_status = status;
6781 }
6782
6783 if (GL_TRUE == status)
6784 {
6785 if (!do_not_detach)
6786 {
6787 for (glw::GLuint i = 0; i < shader_count; ++i)
6788 {
6789 if (shader[i].id)
6790 {
6791 gl.detachShader(program, shader[i].id);
6792
6793 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
6794 }
6795 }
6796 }
6797 }
6798 else
6799 {
6800 glw::GLint log_size = 0;
6801
6802 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
6803
6804 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
6805
6806 glw::GLchar* log_text = new glw::GLchar[log_size];
6807
6808 gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
6809
6810 log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
6811 << log_text << "\n"
6812 << tcu::TestLog::EndMessage;
6813
6814 delete[] log_text;
6815
6816 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
6817
6818 throw 0;
6819 }
6820 }
6821 catch (...)
6822 {
6823 if (program)
6824 {
6825 gl.deleteProgram(program);
6826
6827 program = 0;
6828 }
6829 }
6830
6831 for (glw::GLuint i = 0; i < shader_count; ++i)
6832 {
6833 if (0 != shader[i].id)
6834 {
6835 gl.deleteShader(shader[i].id);
6836
6837 shader[i].id = 0;
6838 }
6839 }
6840
6841 return program;
6842 }
6843
6844 /** @brief Substitute key with value within source code.
6845 *
6846 * @param [in] source Source code to be prerocessed.
6847 * @param [in] key Key to be substituted.
6848 * @param [in] value Value to be inserted.
6849 *
6850 * @return Resulting string.
6851 */
preprocessCode(std::string source,std::string key,std::string value)6852 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value)
6853 {
6854 std::string destination = source;
6855
6856 while (true)
6857 {
6858 /* Find token in source code. */
6859 size_t position = destination.find(key, 0);
6860
6861 /* No more occurences of this key. */
6862 if (position == std::string::npos)
6863 {
6864 break;
6865 }
6866
6867 /* Replace token with sub_code. */
6868 destination.replace(position, key.size(), value);
6869 }
6870
6871 return destination;
6872 }
6873
6874 /** @brief Convert an integer to a string.
6875 *
6876 * @param [in] i Integer to be converted.
6877 *
6878 * @return String representing integer.
6879 */
itoa(glw::GLint i)6880 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i)
6881 {
6882 std::stringstream stream;
6883
6884 stream << i;
6885
6886 return stream.str();
6887 }
6888
6889 /** @brief Convert an float to a string.
6890 *
6891 * @param [in] f Float to be converted.
6892 *
6893 * @return String representing integer.
6894 */
ftoa(glw::GLfloat f)6895 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f)
6896 {
6897 std::stringstream stream;
6898
6899 stream << f;
6900
6901 return stream.str();
6902 }
6903