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_ext_tf_1 = m_context.getContextInfo().isExtensionSupported("GL_EXT_transform_feedback");
3427
3428 bool is_ok = true;
3429 bool test_error = false;
3430
3431 glw::GLuint program = 0;
3432
3433 /* Tests. */
3434 try
3435 {
3436 if (is_at_least_gl_30 || is_ext_tf_1)
3437 {
3438 fetchLimits();
3439
3440 for (glw::GLuint i = 0; (i < s_capture_ways_count) && is_ok; ++i)
3441 {
3442 for (glw::GLuint j = 0; (j < s_shader_cases_count) && is_ok; ++j)
3443 {
3444 for (glw::GLuint k = 0; (k < s_varying_types_count) && is_ok; ++k)
3445 {
3446 glw::GLuint n = numberOfAttributes(i, j, k);
3447
3448 if (n)
3449 {
3450 program = buildProgram(i, j, k, n);
3451
3452 is_ok = is_ok && (program != 0);
3453
3454 is_ok = is_ok && check(program, i, j, k, n);
3455
3456 gl.deleteProgram(program);
3457
3458 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteProgram call failed.");
3459
3460 program = 0;
3461 }
3462 }
3463 }
3464 }
3465 }
3466 }
3467 catch (...)
3468 {
3469 is_ok = false;
3470 test_error = true;
3471
3472 if (program)
3473 {
3474 gl.deleteProgram(program);
3475
3476 program = 0;
3477 }
3478 }
3479
3480 /* Result's setup. */
3481 if (is_ok)
3482 {
3483 /* Log success. */
3484 m_context.getTestContext().getLog() << tcu::TestLog::Message
3485 << "Test checking Get Transform Feedback Varying have passed."
3486 << tcu::TestLog::EndMessage;
3487
3488 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
3489 }
3490 else
3491 {
3492 if (test_error)
3493 {
3494 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
3495 }
3496 else
3497 {
3498 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
3499 }
3500 }
3501
3502 return STOP;
3503 }
3504
buildProgram(glw::GLuint capture_way,glw::GLuint shader_case,glw::GLuint varying_type,glw::GLuint number_of_attributes)3505 glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::buildProgram(glw::GLuint capture_way,
3506 glw::GLuint shader_case,
3507 glw::GLuint varying_type,
3508 glw::GLuint number_of_attributes)
3509 {
3510 /* Functions handler */
3511 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3512
3513 /* Preparing source code. */
3514 std::string xfb_variable_declarations("");
3515 std::string xfb_variable_setters("");
3516 std::vector<std::string> xfb_varyings(number_of_attributes);
3517 std::vector<const glw::GLchar*> xfb_varyings_c(number_of_attributes);
3518
3519 /* Most of varyings is declarated output variables. */
3520 for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3521 {
3522 /* Varying name: result_# */
3523 std::string varying = "result_";
3524 varying.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3525
3526 xfb_varyings[i] = varying;
3527 xfb_varyings_c[i] = xfb_varyings[i].c_str();
3528
3529 /* Varying declaration: out TYPE result_#;*/
3530 xfb_variable_declarations.append("out ");
3531 xfb_variable_declarations.append(s_varying_types[varying_type].name);
3532 xfb_variable_declarations.append(" ");
3533 xfb_variable_declarations.append(varying);
3534 xfb_variable_declarations.append(";\n");
3535
3536 /* Varying setter: result_# = TYPE(#); */
3537 xfb_variable_setters.append(" ");
3538 xfb_variable_setters.append(varying);
3539 xfb_variable_setters.append(" = ");
3540 xfb_variable_setters.append(s_varying_types[varying_type].name);
3541 xfb_variable_setters.append("(");
3542 xfb_variable_setters.append("2"); //gl3cts::TransformFeedback::Utilities::itoa(i));
3543 if (s_varying_types[varying_type].float_component)
3544 {
3545 /* if varying is float varying setter is: result_# = TYPE(#.0); */
3546 xfb_variable_setters.append(".0");
3547 }
3548 xfb_variable_setters.append(");\n");
3549 }
3550
3551 /* Preprocess vertex shader source code template. */
3552 const glw::GLchar* vertex_shader = s_shader_cases[shader_case].vertex_shader;
3553 const glw::GLchar* geometry_shader = s_shader_cases[shader_case].geometry_shader;
3554
3555 std::string xfb_shader;
3556
3557 if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3558 {
3559 /* XFB tested in vertex shader. */
3560 xfb_shader = vertex_shader;
3561 }
3562 else
3563 {
3564 /* XFB tested in geometry shader. */
3565 xfb_shader = geometry_shader;
3566 }
3567
3568 /* Preprocess shader. */
3569 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_DECLARATIONS",
3570 xfb_variable_declarations);
3571 xfb_shader = gl3cts::TransformFeedback::Utilities::preprocessCode(xfb_shader, "TEMPLATE_OUTPUT_SETTERS",
3572 xfb_variable_setters);
3573
3574 if (DE_NULL == s_shader_cases[shader_case].geometry_shader)
3575 {
3576 /* XFB tested in vertex shader. */
3577 vertex_shader = xfb_shader.c_str();
3578 }
3579 else
3580 {
3581 /* XFB tested in geometry shader. */
3582 geometry_shader = xfb_shader.c_str();
3583 }
3584
3585 /* Compile, link and check. */
3586 glw::GLuint program = gl3cts::TransformFeedback::Utilities::buildProgram(
3587 gl, m_context.getTestContext().getLog(), geometry_shader, NULL, NULL, vertex_shader, s_generic_fragment_shader,
3588 &xfb_varyings_c[0], number_of_attributes, s_capture_ways[capture_way]);
3589
3590 /* Check compilation status. */
3591 if (0 == program)
3592 {
3593 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Building program has failed.\nVertex shader:\n"
3594 << vertex_shader << "Geometry shader:\n"
3595 << ((DE_NULL == geometry_shader) ? "" : geometry_shader)
3596 << "Fragment shader:\n"
3597 << s_generic_fragment_shader << tcu::TestLog::EndMessage;
3598
3599 throw 0;
3600 }
3601
3602 return program;
3603 }
3604
check(glw::GLuint program,glw::GLuint capture_way,glw::GLuint shader_case UNUSED,glw::GLuint varying_type,glw::GLuint number_of_attributes)3605 bool gl3cts::TransformFeedback::CheckGetXFBVarying::check(glw::GLuint program, glw::GLuint capture_way,
3606 glw::GLuint shader_case UNUSED, glw::GLuint varying_type,
3607 glw::GLuint number_of_attributes)
3608 {
3609 /* Functions handler */
3610 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3611 glw::GLuint max_length = 0;
3612
3613 /* Inspect glGetTransformFeedbackVarying. */
3614 for (glw::GLuint i = 0; i < number_of_attributes; ++i)
3615 {
3616 const glw::GLsizei bufSize = 18;
3617 glw::GLsizei length = 0;
3618 glw::GLsizei size = 0;
3619 glw::GLenum type = GL_NONE;
3620 glw::GLchar name[18] = { 0 }; /* Size of bufSize. */
3621
3622 gl.getTransformFeedbackVarying(program, i, bufSize, &length, &size, &type, name);
3623
3624 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetTransformFeedbackVarying call failed.");
3625
3626 max_length = deMaxu32(max_length, glw::GLuint(length));
3627
3628 /* Check name. */
3629 if (length)
3630 {
3631 std::string varying = name;
3632 std::string varying_ref = "result_";
3633 varying_ref.append(gl3cts::TransformFeedback::Utilities::itoa(i));
3634
3635 if (0 != varying.compare(varying_ref))
3636 {
3637 return false;
3638 }
3639 }
3640 else
3641 {
3642 return false;
3643 }
3644
3645 /* Check size. */
3646 const glw::GLuint size_ref = 1;
3647
3648 if (size != size_ref)
3649 {
3650 return false;
3651 }
3652
3653 /* Check type. */
3654 if (type != s_varying_types[varying_type].type)
3655 {
3656 return false;
3657 }
3658 }
3659
3660 /* Inspect glGetProgramiv. */
3661 glw::GLint xfb_varyings = 0;
3662 glw::GLint xfb_mode = 0;
3663 glw::GLint xfb_varying_max_length = 0;
3664
3665 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYINGS, &xfb_varyings);
3666 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_BUFFER_MODE, &xfb_mode);
3667 gl.getProgramiv(program, GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH, &xfb_varying_max_length);
3668
3669 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
3670
3671 if (glw::GLuint(xfb_varyings) != number_of_attributes)
3672 {
3673 return false;
3674 }
3675
3676 if (glw::GLenum(xfb_mode) != s_capture_ways[capture_way])
3677 {
3678 return false;
3679 }
3680
3681 if (glw::GLuint(xfb_varying_max_length) < max_length)
3682 {
3683 return false;
3684 }
3685
3686 return true;
3687 }
3688
3689 const glw::GLchar* gl3cts::TransformFeedback::CheckGetXFBVarying::s_generic_fragment_shader = "#version 130\n"
3690 "\n"
3691 "out vec4 color;\n"
3692 "\n"
3693 "void main()\n"
3694 "{\n"
3695 " color = vec4(1.0);\n"
3696 "}\n";
3697
3698 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::ShaderCase
3699 gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases[] = { { /* Vertex Shader. */
3700 "#version 130\n"
3701 "\n"
3702 "TEMPLATE_OUTPUT_DECLARATIONS"
3703 "\n"
3704 "void main()\n"
3705 "{\n"
3706 " gl_Position = vec4(1.0);\n"
3707 "TEMPLATE_OUTPUT_SETTERS"
3708 "}\n",
3709
3710 /* Geometry Shader. */
3711 NULL },
3712 { /* Vertex Shader. */
3713 "#version 130\n"
3714 "\n"
3715 "void main()\n"
3716 "{\n"
3717 "}\n",
3718
3719 /* Geometry Shader. */
3720 "#version 150\n"
3721 "\n"
3722 "layout(points) in;\n"
3723 "layout(points, max_vertices = 1) out;\n"
3724 "\n"
3725 "TEMPLATE_OUTPUT_DECLARATIONS"
3726 "\n"
3727 "void main()\n"
3728 "{\n"
3729 " gl_Position = vec4(1.0);\n"
3730 "TEMPLATE_OUTPUT_SETTERS"
3731 " EmitVertex();\n"
3732 "}\n" } };
3733
3734 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_shader_cases_count =
3735 sizeof(s_shader_cases) / sizeof(s_shader_cases[0]);
3736
3737 const struct gl3cts::TransformFeedback::CheckGetXFBVarying::VaryingType
3738 gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types[] = {
3739 /* type, name, #components, is component float */
3740 { GL_FLOAT, "float", 1, true },
3741 { GL_FLOAT_VEC2, "vec2", 2, true },
3742 { GL_FLOAT_VEC3, "vec3", 3, true },
3743 { GL_FLOAT_VEC4, "vec4", 4, true },
3744 { GL_INT, "int", 1, false },
3745 { GL_INT_VEC2, "ivec2", 2, false },
3746 { GL_INT_VEC3, "ivec3", 3, false },
3747 { GL_INT_VEC4, "ivec4", 4, false },
3748 { GL_UNSIGNED_INT, "uint", 1, false },
3749 { GL_UNSIGNED_INT_VEC2, "uvec2", 2, false },
3750 { GL_UNSIGNED_INT_VEC3, "uvec3", 3, false },
3751 { GL_UNSIGNED_INT_VEC4, "uvec4", 4, false },
3752 { GL_FLOAT_MAT2, "mat2", 4, true },
3753 { GL_FLOAT_MAT3, "mat3", 9, true },
3754 { GL_FLOAT_MAT4, "mat4", 16, true }
3755 };
3756
3757 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_varying_types_count =
3758 sizeof(s_varying_types) / sizeof(s_varying_types[0]);
3759
3760 const glw::GLenum gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways[] = { GL_INTERLEAVED_ATTRIBS,
3761 GL_SEPARATE_ATTRIBS };
3762
3763 const glw::GLuint gl3cts::TransformFeedback::CheckGetXFBVarying::s_capture_ways_count =
3764 sizeof(s_capture_ways) / sizeof(s_capture_ways[0]);
3765
3766 /*-----------------------------------------------------------------------------------------------*/
3767
QueryVertexInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3768 gl3cts::TransformFeedback::QueryVertexInterleaved::QueryVertexInterleaved(deqp::Context& context, const char* test_name,
3769 const char* test_description)
3770 : CaptureVertexInterleaved(context, test_name, test_description), m_query_object(0)
3771 {
3772 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3773 }
3774
createTransformFeedbackBuffer(void)3775 void gl3cts::TransformFeedback::QueryVertexInterleaved::createTransformFeedbackBuffer(void)
3776 {
3777 /* Functions handler */
3778 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3779
3780 /* Create buffer object. */
3781 gl3cts::TransformFeedback::CaptureVertexInterleaved::createTransformFeedbackBuffer();
3782
3783 /* Create query object. */
3784 gl.genQueries(1, &m_query_object);
3785 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3786 }
3787
draw(glw::GLuint primitive_case)3788 void gl3cts::TransformFeedback::QueryVertexInterleaved::draw(glw::GLuint primitive_case)
3789 {
3790 /* Functions handler */
3791 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3792
3793 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3794 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3795
3796 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
3797
3798 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3799 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3800 }
3801
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3802 bool gl3cts::TransformFeedback::QueryVertexInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3803 glw::GLenum primitive_type)
3804 {
3805 /* Functions handler */
3806 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3807
3808 glw::GLuint number_of_primitives;
3809
3810 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3811 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3812
3813 /* expected result */
3814 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3815
3816 if (number_of_primitives_reference != number_of_primitives)
3817 {
3818 return false;
3819 }
3820
3821 return true;
3822 }
3823
clean(void)3824 void gl3cts::TransformFeedback::QueryVertexInterleaved::clean(void)
3825 {
3826 /* Functions handler */
3827 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3828
3829 /* Delete query object. */
3830 gl.deleteQueries(1, &m_query_object);
3831 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3832
3833 /* Other */
3834 gl3cts::TransformFeedback::CaptureVertexInterleaved::clean();
3835 }
3836
3837 /*-----------------------------------------------------------------------------------------------*/
3838
QueryGeometryInterleaved(deqp::Context & context,const char * test_name,const char * test_description)3839 gl3cts::TransformFeedback::QueryGeometryInterleaved::QueryGeometryInterleaved(deqp::Context& context,
3840 const char* test_name,
3841 const char* test_description)
3842 : CaptureVertexInterleaved(context, test_name, test_description)
3843 , CaptureGeometryInterleaved(context, test_name, test_description)
3844 {
3845 m_query_object = 0;
3846 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3847 }
3848
createTransformFeedbackBuffer(void)3849 void gl3cts::TransformFeedback::QueryGeometryInterleaved::createTransformFeedbackBuffer(void)
3850 {
3851 /* Functions handler */
3852 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3853
3854 /* Create buffer object. */
3855 gl3cts::TransformFeedback::CaptureGeometryInterleaved::createTransformFeedbackBuffer();
3856
3857 /* Create query object. */
3858 gl.genQueries(1, &m_query_object);
3859 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3860 }
3861
draw(glw::GLuint primitive_case)3862 void gl3cts::TransformFeedback::QueryGeometryInterleaved::draw(glw::GLuint primitive_case)
3863 {
3864 /* Functions handler */
3865 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3866
3867 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3868 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3869
3870 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
3871
3872 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3873 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3874 }
3875
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3876 bool gl3cts::TransformFeedback::QueryGeometryInterleaved::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3877 glw::GLenum primitive_type)
3878 {
3879 /* Functions handler */
3880 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3881
3882 glw::GLuint number_of_primitives;
3883
3884 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3885 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3886
3887 /* expected result */
3888 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3889
3890 if (number_of_primitives_reference != number_of_primitives)
3891 {
3892 return false;
3893 }
3894
3895 return true;
3896 }
3897
clean(void)3898 void gl3cts::TransformFeedback::QueryGeometryInterleaved::clean(void)
3899 {
3900 /* Functions handler */
3901 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3902
3903 /* Delete query object. */
3904 gl.deleteQueries(1, &m_query_object);
3905 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3906
3907 /* Other. */
3908 gl3cts::TransformFeedback::CaptureGeometryInterleaved::clean();
3909 }
3910
3911 /*-----------------------------------------------------------------------------------------------*/
3912
QueryVertexSeparate(deqp::Context & context,const char * test_name,const char * test_description)3913 gl3cts::TransformFeedback::QueryVertexSeparate::QueryVertexSeparate(deqp::Context& context, const char* test_name,
3914 const char* test_description)
3915 : CaptureVertexInterleaved(context, test_name, test_description)
3916 , CaptureVertexSeparate(context, test_name, test_description)
3917 {
3918 m_query_object = 0;
3919 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3920 }
3921
createTransformFeedbackBuffer(void)3922 void gl3cts::TransformFeedback::QueryVertexSeparate::createTransformFeedbackBuffer(void)
3923 {
3924 /* Functions handler */
3925 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3926
3927 /* Create buffer object. */
3928 gl3cts::TransformFeedback::CaptureVertexSeparate::createTransformFeedbackBuffer();
3929
3930 /* Create query object. */
3931 gl.genQueries(1, &m_query_object);
3932 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
3933 }
3934
draw(glw::GLuint primitive_case)3935 void gl3cts::TransformFeedback::QueryVertexSeparate::draw(glw::GLuint primitive_case)
3936 {
3937 /* Functions handler */
3938 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3939
3940 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
3941 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
3942
3943 gl3cts::TransformFeedback::CaptureVertexSeparate::draw(primitive_case);
3944
3945 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
3946 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
3947 }
3948
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)3949 bool gl3cts::TransformFeedback::QueryVertexSeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
3950 glw::GLenum primitive_type)
3951 {
3952 /* Functions handler */
3953 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3954
3955 glw::GLuint number_of_primitives;
3956
3957 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
3958 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
3959
3960 /* expected result */
3961 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
3962
3963 if (number_of_primitives_reference != number_of_primitives)
3964 {
3965 return false;
3966 }
3967
3968 return true;
3969 }
3970
clean(void)3971 void gl3cts::TransformFeedback::QueryVertexSeparate::clean(void)
3972 {
3973 /* Functions handler */
3974 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
3975
3976 /* Delete query object. */
3977 gl.deleteQueries(1, &m_query_object);
3978 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
3979
3980 /* Other */
3981 gl3cts::TransformFeedback::CaptureVertexSeparate::clean();
3982 }
3983
3984 /*-----------------------------------------------------------------------------------------------*/
3985
QueryGeometrySeparate(deqp::Context & context,const char * test_name,const char * test_description)3986 gl3cts::TransformFeedback::QueryGeometrySeparate::QueryGeometrySeparate(deqp::Context& context, const char* test_name,
3987 const char* test_description)
3988 : CaptureVertexInterleaved(context, test_name, test_description)
3989 , CaptureVertexSeparate(context, test_name, test_description)
3990 , CaptureGeometrySeparate(context, test_name, test_description)
3991 {
3992 m_query_object = 0;
3993 m_max_vertices_drawn = 3; /* Make buffer smaller up to 3 vertices. */
3994 }
3995
createTransformFeedbackBuffer(void)3996 void gl3cts::TransformFeedback::QueryGeometrySeparate::createTransformFeedbackBuffer(void)
3997 {
3998 /* Functions handler */
3999 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4000
4001 /* Create buffer object. */
4002 gl3cts::TransformFeedback::CaptureGeometrySeparate::createTransformFeedbackBuffer();
4003
4004 /* Create query object. */
4005 gl.genQueries(1, &m_query_object);
4006 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
4007 }
4008
draw(glw::GLuint primitive_case)4009 void gl3cts::TransformFeedback::QueryGeometrySeparate::draw(glw::GLuint primitive_case)
4010 {
4011 /* Functions handler */
4012 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4013
4014 gl.beginQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, m_query_object);
4015 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQuery call failed.");
4016
4017 gl3cts::TransformFeedback::CaptureGeometrySeparate::draw(primitive_case);
4018
4019 gl.endQuery(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN);
4020 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQuery call failed.");
4021 }
4022
checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,glw::GLenum primitive_type)4023 bool gl3cts::TransformFeedback::QueryGeometrySeparate::checkTransformFeedbackBuffer(BindBufferCase bind_case UNUSED,
4024 glw::GLenum primitive_type)
4025 {
4026 /* Functions handler */
4027 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4028
4029 glw::GLuint number_of_primitives;
4030
4031 gl.getQueryObjectuiv(m_query_object, GL_QUERY_RESULT, &number_of_primitives);
4032 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv call failed.");
4033
4034 /* expected result */
4035 glw::GLuint number_of_primitives_reference = (primitive_type == GL_POINTS) ? 3 : 1; /* m_max_vertices_drawn == 3 */
4036
4037 if (number_of_primitives_reference != number_of_primitives)
4038 {
4039 return false;
4040 }
4041
4042 return true;
4043 }
4044
clean(void)4045 void gl3cts::TransformFeedback::QueryGeometrySeparate::clean(void)
4046 {
4047 /* Functions handler */
4048 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4049
4050 /* Delete query object. */
4051 gl.deleteQueries(1, &m_query_object);
4052 GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteQueries call failed.");
4053
4054 /* Other */
4055 gl3cts::TransformFeedback::CaptureGeometrySeparate::clean();
4056 }
4057
4058 /*-----------------------------------------------------------------------------------------------*/
4059
DiscardVertex(deqp::Context & context,const char * test_name,const char * test_description)4060 gl3cts::TransformFeedback::DiscardVertex::DiscardVertex(deqp::Context& context, const char* test_name,
4061 const char* test_description)
4062 : CaptureVertexInterleaved(context, test_name, test_description)
4063 {
4064 }
4065
draw(glw::GLuint primitive_case)4066 void gl3cts::TransformFeedback::DiscardVertex::draw(glw::GLuint primitive_case)
4067 {
4068 /* Functions handler */
4069 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4070
4071 /* Must clear before rasterizer discard */
4072 gl.clear(GL_COLOR_BUFFER_BIT);
4073 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4074
4075 gl.enable(GL_RASTERIZER_DISCARD);
4076 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4077
4078 gl3cts::TransformFeedback::CaptureVertexInterleaved::draw(primitive_case);
4079
4080 gl.disable(GL_RASTERIZER_DISCARD);
4081 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4082 }
4083
checkFramebuffer(glw::GLuint primitive_case UNUSED)4084 bool gl3cts::TransformFeedback::DiscardVertex::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4085 {
4086 /* Functions handler */
4087 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4088
4089 /* Fetch framebuffer. */
4090 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4091
4092 if (s_framebuffer_size > 0)
4093 {
4094 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4095 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4096 }
4097
4098 /* Check results.
4099 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4100 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4101 {
4102 if (fabs(*i) > 0.0625f /* precision */)
4103 {
4104 return false;
4105 }
4106 }
4107
4108 return true;
4109 }
4110
4111 /*-----------------------------------------------------------------------------------------------*/
4112
DiscardGeometry(deqp::Context & context,const char * test_name,const char * test_description)4113 gl3cts::TransformFeedback::DiscardGeometry::DiscardGeometry(deqp::Context& context, const char* test_name,
4114 const char* test_description)
4115 : CaptureVertexInterleaved(context, test_name, test_description)
4116 , CaptureGeometryInterleaved(context, test_name, test_description)
4117 {
4118 }
4119
draw(glw::GLuint primitive_case)4120 void gl3cts::TransformFeedback::DiscardGeometry::draw(glw::GLuint primitive_case)
4121 {
4122 /* Functions handler */
4123 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4124
4125 /* Must clear before rasterizer discard */
4126 gl.clear(GL_COLOR_BUFFER_BIT);
4127 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4128
4129 gl.enable(GL_RASTERIZER_DISCARD);
4130 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4131
4132 gl3cts::TransformFeedback::CaptureGeometryInterleaved::draw(primitive_case);
4133
4134 gl.disable(GL_RASTERIZER_DISCARD);
4135 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4136 }
4137
checkFramebuffer(glw::GLuint primitive_case UNUSED)4138 bool gl3cts::TransformFeedback::DiscardGeometry::checkFramebuffer(glw::GLuint primitive_case UNUSED)
4139 {
4140 /* Functions handler */
4141 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4142
4143 /* Fetch framebuffer. */
4144 std::vector<glw::GLfloat> pixels(s_framebuffer_size * s_framebuffer_size);
4145
4146 if (s_framebuffer_size > 0)
4147 {
4148 gl.readPixels(0, 0, s_framebuffer_size, s_framebuffer_size, GL_RED, GL_FLOAT, pixels.data());
4149 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4150 }
4151
4152 /* Check results.
4153 Note: assuming that s_buffer_size == 2 -> then all points shall be drawn. */
4154 for (std::vector<glw::GLfloat>::iterator i = pixels.begin(); i != pixels.end(); ++i)
4155 {
4156 if (fabs(*i) > 0.0625f /* precision */)
4157 {
4158 return false;
4159 }
4160 }
4161
4162 return true;
4163 }
4164
4165 /*-----------------------------------------------------------------------------------------------*/
4166
DrawXFB(deqp::Context & context,const char * test_name,const char * test_description)4167 gl3cts::TransformFeedback::DrawXFB::DrawXFB(deqp::Context& context, const char* test_name, const char* test_description)
4168 : deqp::TestCase(context, test_name, test_description)
4169 , m_context(context)
4170 , m_program_id_xfb(0)
4171 , m_program_id_draw(0)
4172 , m_fbo_id(0)
4173 , m_rbo_id(0)
4174 , m_vao_id(0)
4175 {
4176 memset(m_xfb_id, 0, sizeof(m_xfb_id));
4177 memset(m_bo_id, 0, sizeof(m_bo_id));
4178 }
4179
~DrawXFB(void)4180 gl3cts::TransformFeedback::DrawXFB::~DrawXFB(void)
4181 {
4182 }
4183
iterate(void)4184 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFB::iterate(void)
4185 {
4186 /* Initializations. */
4187 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4188 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4189
4190 bool is_ok = true;
4191 bool test_error = false;
4192
4193 /* Tests. */
4194 try
4195 {
4196 if (is_at_least_gl_40 || is_arb_tf_2)
4197 {
4198 for (glw::GLuint i = 0; (i < s_capture_modes_count) && is_ok; ++i)
4199 {
4200 prepare(s_capture_modes[i]);
4201
4202 bindVAO(m_vao_id);
4203 useProgram(m_program_id_xfb);
4204
4205 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4206 {
4207 bindXFB(m_xfb_id[j]);
4208 bindBOForXFB(s_capture_modes[i], m_bo_id[j]);
4209 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4210 useGeometrySet(m_program_id_xfb, false);
4211 drawForCapture(true, true, false, false);
4212
4213 is_ok = is_ok && inspectXFBState(true, true);
4214 }
4215
4216 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4217 {
4218 bindXFB(m_xfb_id[j]);
4219 useColour(m_program_id_xfb, s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4220 useGeometrySet(m_program_id_xfb, true);
4221 drawForCapture(false, false, true, true);
4222
4223 is_ok = is_ok && inspectXFBState(false, false);
4224 }
4225
4226 useProgram(m_program_id_draw);
4227
4228 for (glw::GLuint j = 0; (j < s_xfb_count) && is_ok; ++j)
4229 {
4230 bindXFB(m_xfb_id[j]);
4231 bindBOForDraw(m_program_id_draw, s_capture_modes[i], m_bo_id[j]);
4232 drawToFramebuffer(m_xfb_id[j]);
4233
4234 is_ok =
4235 is_ok && checkFramebuffer(s_colours[j][0], s_colours[j][1], s_colours[j][2], s_colours[j][3]);
4236 }
4237
4238 clean();
4239 }
4240 }
4241 }
4242 catch (...)
4243 {
4244 is_ok = false;
4245 test_error = true;
4246 clean();
4247 }
4248
4249 /* Result's setup. */
4250 if (is_ok)
4251 {
4252 /* Log success. */
4253 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have passed."
4254 << tcu::TestLog::EndMessage;
4255
4256 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4257 }
4258 else
4259 {
4260 if (test_error)
4261 {
4262 /* Log error. */
4263 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have approached error."
4264 << tcu::TestLog::EndMessage;
4265
4266 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4267 }
4268 else
4269 {
4270 /* Log fail. */
4271 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB have failed."
4272 << tcu::TestLog::EndMessage;
4273
4274 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4275 }
4276 }
4277
4278 return STOP;
4279 }
4280
prepare(glw::GLenum capture_mode)4281 void gl3cts::TransformFeedback::DrawXFB::prepare(glw::GLenum capture_mode)
4282 {
4283 /* Functions handler */
4284 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4285
4286 /* Prepare programs. */
4287 m_program_id_xfb = gl3cts::TransformFeedback::Utilities::buildProgram(
4288 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_xfb, s_fragment_shader,
4289 s_xfb_varyings, s_xfb_varyings_count, capture_mode);
4290
4291 if (0 == m_program_id_xfb)
4292 {
4293 throw 0;
4294 }
4295
4296 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(),
4297 NULL, NULL, NULL, s_vertex_shader_draw,
4298 s_fragment_shader, NULL, 0, capture_mode);
4299
4300 if (0 == m_program_id_draw)
4301 {
4302 throw 0;
4303 }
4304
4305 /* Prepare transform feedbacks. */
4306 gl.genTransformFeedbacks(s_xfb_count, m_xfb_id);
4307 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4308
4309 /* Prepare buffer objects. */
4310 gl.genBuffers(s_xfb_count, m_bo_id);
4311 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4312
4313 for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4314 {
4315 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
4316 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4317
4318 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_capture_size, NULL, GL_DYNAMIC_COPY);
4319 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4320 }
4321
4322 /* Prepare framebuffer. */
4323 gl.clearColor(0.f, 0.f, 0.f, 1.f);
4324 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4325
4326 gl.genFramebuffers(1, &m_fbo_id);
4327 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
4328
4329 gl.genRenderbuffers(1, &m_rbo_id);
4330 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
4331
4332 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
4333 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
4334
4335 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
4336 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
4337
4338 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, s_view_size, s_view_size);
4339 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
4340
4341 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
4342 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
4343
4344 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
4345 {
4346 throw 0;
4347 }
4348
4349 gl.viewport(0, 0, s_view_size, s_view_size);
4350 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
4351
4352 /* Create empty Vertex Array Object */
4353 gl.genVertexArrays(1, &m_vao_id);
4354 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4355 }
4356
bindXFB(glw::GLuint xfb_id)4357 void gl3cts::TransformFeedback::DrawXFB::bindXFB(glw::GLuint xfb_id)
4358 {
4359 /* Functions handler */
4360 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4361
4362 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, xfb_id);
4363 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedback call failed.");
4364 }
4365
bindVAO(glw::GLuint vao_id)4366 void gl3cts::TransformFeedback::DrawXFB::bindVAO(glw::GLuint vao_id)
4367 {
4368 /* Functions handler */
4369 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4370
4371 gl.bindVertexArray(vao_id);
4372 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4373 }
4374
bindBOForXFB(glw::GLenum capture_mode,glw::GLuint bo_id)4375 void gl3cts::TransformFeedback::DrawXFB::bindBOForXFB(glw::GLenum capture_mode, glw::GLuint bo_id)
4376 {
4377 /* Functions handler */
4378 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4379
4380 switch (capture_mode)
4381 {
4382 case GL_INTERLEAVED_ATTRIBS:
4383 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, bo_id);
4384 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4385 break;
4386 case GL_SEPARATE_ATTRIBS:
4387 for (glw::GLuint i = 0; i < s_xfb_varyings_count; ++i)
4388 {
4389 gl.bindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i, bo_id, i * s_capture_size / s_xfb_varyings_count,
4390 (i + 1) * s_capture_size / s_xfb_varyings_count);
4391 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase call failed.");
4392 }
4393 break;
4394 default:
4395 throw 0;
4396 }
4397 }
4398
bindBOForDraw(glw::GLuint program_id,glw::GLenum capture_mode,glw::GLuint bo_id)4399 void gl3cts::TransformFeedback::DrawXFB::bindBOForDraw(glw::GLuint program_id, glw::GLenum capture_mode,
4400 glw::GLuint bo_id)
4401 {
4402 /* Functions handler */
4403 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4404
4405 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
4406
4407 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4408
4409 glw::GLuint position_location = gl.getAttribLocation(program_id, "position");
4410 glw::GLuint color_location = gl.getAttribLocation(program_id, "color");
4411
4412 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4413
4414 glw::GLvoid* color_offset = (capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4415 (glw::GLvoid*)(4 /* components */ * sizeof(glw::GLfloat)) :
4416 (glw::GLvoid*)(4 /* components */ * 6 /* vertices */ * sizeof(glw::GLfloat));
4417
4418 glw::GLuint stride =
4419 static_cast<glw::GLuint>((capture_mode == GL_INTERLEAVED_ATTRIBS) ?
4420 (4 /* components */ * 2 /* position and color */ * sizeof(glw::GLfloat)) :
4421 (4 /* components */ * sizeof(glw::GLfloat)));
4422
4423 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, stride, NULL);
4424 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, stride, color_offset);
4425
4426 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4427
4428 gl.enableVertexAttribArray(position_location);
4429 gl.enableVertexAttribArray(color_location);
4430
4431 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4432 }
4433
useProgram(glw::GLuint program_id)4434 void gl3cts::TransformFeedback::DrawXFB::useProgram(glw::GLuint program_id)
4435 {
4436 /* Functions handler */
4437 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4438
4439 gl.useProgram(program_id);
4440 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4441 }
4442
useColour(glw::GLuint program_id,glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4443 void gl3cts::TransformFeedback::DrawXFB::useColour(glw::GLuint program_id, glw::GLfloat r, glw::GLfloat g,
4444 glw::GLfloat b, glw::GLfloat a)
4445 {
4446 /* Functions handler */
4447 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4448
4449 glw::GLint location = gl.getUniformLocation(program_id, "color");
4450 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4451
4452 gl.uniform4f(location, r, g, b, a);
4453 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4454 }
4455
useGeometrySet(glw::GLuint program_id,bool invert_sign)4456 void gl3cts::TransformFeedback::DrawXFB::useGeometrySet(glw::GLuint program_id, bool invert_sign)
4457 {
4458 /* Functions handler */
4459 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4460
4461 glw::GLint location = gl.getUniformLocation(program_id, "invert_sign");
4462 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformLocation call failed.");
4463
4464 gl.uniform1f(location, invert_sign ? -1.f : 1.f);
4465 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniform4f call failed.");
4466 }
4467
clean()4468 void gl3cts::TransformFeedback::DrawXFB::clean()
4469 {
4470 /* Functions handler */
4471 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4472
4473 gl.useProgram(0);
4474
4475 if (m_program_id_xfb)
4476 {
4477 gl.deleteProgram(m_program_id_xfb);
4478
4479 m_program_id_xfb = 0;
4480 }
4481
4482 if (m_program_id_draw)
4483 {
4484 gl.deleteProgram(m_program_id_draw);
4485
4486 m_program_id_draw = 1;
4487 }
4488
4489 for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4490 {
4491 if (m_xfb_id[i])
4492 {
4493 gl.deleteTransformFeedbacks(1, &m_xfb_id[i]);
4494
4495 m_xfb_id[i] = 0;
4496 }
4497 }
4498
4499 for (glw::GLuint i = 0; i < s_xfb_count; ++i)
4500 {
4501 if (m_bo_id[i])
4502 {
4503 gl.deleteBuffers(1, &m_bo_id[i]);
4504
4505 m_bo_id[i] = 0;
4506 }
4507 }
4508
4509 if (m_vao_id)
4510 {
4511 gl.deleteVertexArrays(1, &m_vao_id);
4512
4513 m_vao_id = 0;
4514 }
4515
4516 if (m_fbo_id)
4517 {
4518 gl.deleteFramebuffers(1, &m_fbo_id);
4519
4520 m_fbo_id = 0;
4521 }
4522
4523 if (m_rbo_id)
4524 {
4525 gl.deleteRenderbuffers(1, &m_rbo_id);
4526
4527 m_rbo_id = 0;
4528 }
4529 }
4530
drawForCapture(bool begin_xfb,bool pause_xfb,bool resume_xfb,bool end_xfb)4531 void gl3cts::TransformFeedback::DrawXFB::drawForCapture(bool begin_xfb, bool pause_xfb, bool resume_xfb, bool end_xfb)
4532 {
4533 /* Functions handler */
4534 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4535
4536 gl.enable(GL_RASTERIZER_DISCARD);
4537 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4538
4539 if (begin_xfb)
4540 {
4541 gl.beginTransformFeedback(GL_POINTS);
4542 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4543 }
4544
4545 if (resume_xfb)
4546 {
4547 gl.resumeTransformFeedback();
4548 GLU_EXPECT_NO_ERROR(gl.getError(), "glResumeTransformFeedback call failed.");
4549 }
4550
4551 gl.drawArrays(GL_POINTS, 0, 3);
4552
4553 if (pause_xfb)
4554 {
4555 gl.pauseTransformFeedback();
4556 GLU_EXPECT_NO_ERROR(gl.getError(), "glPauseTransformFeedback call failed.");
4557 }
4558
4559 if (end_xfb)
4560 {
4561 gl.endTransformFeedback();
4562 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4563 }
4564
4565 gl.disable(GL_RASTERIZER_DISCARD);
4566 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4567 }
4568
drawToFramebuffer(glw::GLuint xfb_id)4569 void gl3cts::TransformFeedback::DrawXFB::drawToFramebuffer(glw::GLuint xfb_id)
4570 {
4571 /* Functions handler */
4572 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4573
4574 gl.clearColor(0.f, 0.f, 0.f, 0.f);
4575 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
4576
4577 gl.clear(GL_COLOR_BUFFER_BIT);
4578 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
4579
4580 gl.drawTransformFeedback(GL_TRIANGLES, xfb_id);
4581 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4582 }
4583
checkFramebuffer(glw::GLfloat r,glw::GLfloat g,glw::GLfloat b,glw::GLfloat a)4584 bool gl3cts::TransformFeedback::DrawXFB::checkFramebuffer(glw::GLfloat r, glw::GLfloat g, glw::GLfloat b,
4585 glw::GLfloat a)
4586 {
4587 /* Functions handler */
4588 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4589
4590 /* Number of pixels. */
4591 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
4592
4593 /* Fetch framebuffer. */
4594 std::vector<glw::GLubyte> pixels(number_of_pixels * 4 /* components */);
4595
4596 if (s_view_size > 0)
4597 {
4598 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RGBA, GL_UNSIGNED_BYTE, pixels.data());
4599 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
4600 }
4601
4602 /* Convert color to integer. */
4603 glw::GLubyte ir = (glw::GLubyte)(255.f * r);
4604 glw::GLubyte ig = (glw::GLubyte)(255.f * g);
4605 glw::GLubyte ib = (glw::GLubyte)(255.f * b);
4606 glw::GLubyte ia = (glw::GLubyte)(255.f * a);
4607
4608 /* Check results. */
4609 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
4610 {
4611 if ((pixels[i * 4 /* components */] != ir) || (pixels[i * 4 /* components */ + 1] != ig) ||
4612 (pixels[i * 4 /* components */ + 2] != ib) || (pixels[i * 4 /* components */ + 3] != ia))
4613 {
4614 return false;
4615 }
4616 }
4617
4618 return true;
4619 }
4620
inspectXFBState(bool shall_be_paused,bool shall_be_active)4621 bool gl3cts::TransformFeedback::DrawXFB::inspectXFBState(bool shall_be_paused, bool shall_be_active)
4622 {
4623 /* Functions handler */
4624 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4625
4626 glw::GLint is_paused = 0;
4627 glw::GLint is_active = 0;
4628
4629 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_PAUSED, &is_paused);
4630 gl.getIntegerv(GL_TRANSFORM_FEEDBACK_ACTIVE, &is_active);
4631
4632 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
4633
4634 if ((is_paused == -1) || (is_active == -1))
4635 {
4636 throw 0;
4637 }
4638
4639 if (shall_be_paused ^ (is_paused == GL_TRUE))
4640 {
4641 return false;
4642 }
4643
4644 if (shall_be_active ^ (is_active == GL_TRUE))
4645 {
4646 return false;
4647 }
4648
4649 return true;
4650 }
4651
4652 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_xfb =
4653 "#version 130\n"
4654 "\n"
4655 "uniform vec4 color;\n"
4656 "uniform float invert_sign;\n"
4657 "out vec4 colour;\n"
4658 "\n"
4659 "void main()\n"
4660 "{\n"
4661 " switch(gl_VertexID)\n"
4662 " {\n"
4663 " case 0:\n"
4664 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
4665 " break;\n"
4666 " case 1:\n"
4667 " gl_Position = vec4(-1.0 * invert_sign, 1.0, 0.0, 1.0);\n"
4668 " break;\n"
4669 " case 2:\n"
4670 " gl_Position = vec4( 1.0, 1.0 * invert_sign, 0.0, 1.0);\n"
4671 " break;\n"
4672 " }\n"
4673 "\n"
4674 " colour = color;\n"
4675 "}\n";
4676
4677 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_vertex_shader_draw = "#version 130\n"
4678 "\n"
4679 "in vec4 color;\n"
4680 "in vec4 position;\n"
4681 "out vec4 colour;\n"
4682 "\n"
4683 "void main()\n"
4684 "{\n"
4685 " gl_Position = position;\n"
4686 " colour = color;\n"
4687 "}\n";
4688
4689 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_fragment_shader = "#version 130\n"
4690 "\n"
4691 "in vec4 colour;\n"
4692 "out vec4 pixel;\n"
4693 "\n"
4694 "void main()\n"
4695 "{\n"
4696 " pixel = colour;\n"
4697 "}\n";
4698
4699 const glw::GLchar* gl3cts::TransformFeedback::DrawXFB::s_xfb_varyings[s_xfb_varyings_count] = { "gl_Position",
4700 "colour" };
4701
4702 const glw::GLenum gl3cts::TransformFeedback::DrawXFB::s_capture_modes[] = { GL_INTERLEAVED_ATTRIBS,
4703 GL_SEPARATE_ATTRIBS };
4704 const glw::GLuint gl3cts::TransformFeedback::DrawXFB::s_capture_modes_count =
4705 sizeof(s_capture_modes) / sizeof(s_capture_modes[0]);
4706
4707 const glw::GLfloat gl3cts::TransformFeedback::DrawXFB::s_colours[s_xfb_count][4] = { { 1.f, 0.f, 0.f, 1.f },
4708 { 0.f, 1.f, 0.f, 1.f },
4709 { 0.f, 0.f, 1.f, 1.f } };
4710
4711 /*-----------------------------------------------------------------------------------------------*/
4712
DrawXFBFeedback(deqp::Context & context,const char * test_name,const char * test_description)4713 gl3cts::TransformFeedback::DrawXFBFeedback::DrawXFBFeedback(deqp::Context& context, const char* test_name,
4714 const char* test_description)
4715 : deqp::TestCase(context, test_name, test_description)
4716 , m_context(context)
4717 , m_program_id(0)
4718 , m_xfb_id(0)
4719 , m_source_bo_index(0)
4720 {
4721 memset(m_bo_id, 1, sizeof(m_bo_id));
4722 memset(m_bo_id, 1, sizeof(m_vao_id));
4723 }
4724
~DrawXFBFeedback(void)4725 gl3cts::TransformFeedback::DrawXFBFeedback::~DrawXFBFeedback(void)
4726 {
4727 }
4728
iterate(void)4729 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBFeedback::iterate(void)
4730 {
4731 /* Initializations. */
4732 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
4733 bool is_arb_tf_2 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2");
4734
4735 bool is_ok = true;
4736 bool test_error = false;
4737
4738 /* Tests. */
4739 try
4740 {
4741 if (is_at_least_gl_40 || is_arb_tf_2)
4742 {
4743 prepareAndBind();
4744 draw(true);
4745 swapBuffers();
4746 draw(false);
4747 swapBuffers();
4748 draw(false);
4749
4750 is_ok = is_ok && check();
4751 }
4752 }
4753 catch (...)
4754 {
4755 is_ok = false;
4756 test_error = true;
4757 }
4758
4759 /* Clean GL objects. */
4760 clean();
4761
4762 /* Result's setup. */
4763 if (is_ok)
4764 {
4765 /* Log success. */
4766 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have passed."
4767 << tcu::TestLog::EndMessage;
4768
4769 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
4770 }
4771 else
4772 {
4773 if (test_error)
4774 {
4775 /* Log error. */
4776 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have approached error."
4777 << tcu::TestLog::EndMessage;
4778
4779 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
4780 }
4781 else
4782 {
4783 /* Log fail. */
4784 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Feedback have failed."
4785 << tcu::TestLog::EndMessage;
4786
4787 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
4788 }
4789 }
4790
4791 return STOP;
4792 }
4793
prepareAndBind()4794 void gl3cts::TransformFeedback::DrawXFBFeedback::prepareAndBind()
4795 {
4796 /* Functions handler */
4797 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4798
4799 /* Prepare programs. */
4800 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(gl, m_context.getTestContext().getLog(), NULL,
4801 NULL, NULL, s_vertex_shader, s_fragment_shader,
4802 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
4803
4804 if (0 == m_program_id)
4805 {
4806 throw 0;
4807 }
4808
4809 gl.useProgram(m_program_id);
4810 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
4811
4812 /* Prepare transform feedbacks. */
4813 gl.genTransformFeedbacks(1, &m_xfb_id);
4814 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
4815
4816 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
4817 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
4818
4819 /* Prepare buffer objects. */
4820 gl.genBuffers(s_bo_count, m_bo_id);
4821 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
4822
4823 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[0]);
4824 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4825
4826 gl.bufferData(GL_ARRAY_BUFFER, s_bo_size, s_initial_data, GL_DYNAMIC_COPY);
4827 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4828
4829 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[1]);
4830 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4831
4832 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY);
4833 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
4834
4835 /* Setup vertex arrays. */
4836 gl.genVertexArrays(s_bo_count, m_vao_id);
4837 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
4838
4839 glw::GLuint position_location = gl.getAttribLocation(m_program_id, "position");
4840 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
4841
4842 for (glw::GLuint i = 0; i < 2; ++i)
4843 {
4844 gl.bindVertexArray(m_vao_id[i]);
4845 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4846
4847 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id[i]);
4848 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4849
4850 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
4851 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
4852
4853 gl.enableVertexAttribArray(position_location);
4854 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
4855 }
4856
4857 gl.bindBuffer(GL_ARRAY_BUFFER, 0);
4858 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4859
4860 gl.bindVertexArray(m_vao_id[0]);
4861 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4862 }
4863
swapBuffers()4864 void gl3cts::TransformFeedback::DrawXFBFeedback::swapBuffers()
4865 {
4866 /* Functions handler */
4867 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4868
4869 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id[m_source_bo_index]);
4870 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
4871
4872 m_source_bo_index = (m_source_bo_index + 1) % 2;
4873
4874 gl.bindVertexArray(m_vao_id[(m_source_bo_index)]);
4875 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
4876 }
4877
draw(bool is_first_draw)4878 void gl3cts::TransformFeedback::DrawXFBFeedback::draw(bool is_first_draw)
4879 {
4880 /* Functions handler */
4881 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4882
4883 gl.enable(GL_RASTERIZER_DISCARD);
4884 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
4885
4886 gl.beginTransformFeedback(GL_POINTS);
4887 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
4888
4889 if (is_first_draw)
4890 {
4891 gl.drawArrays(GL_POINTS, 0, 1);
4892 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
4893 }
4894 else
4895 {
4896 gl.drawTransformFeedback(GL_POINTS, m_xfb_id);
4897 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedback call failed.");
4898 }
4899
4900 gl.endTransformFeedback();
4901 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
4902
4903 gl.disable(GL_RASTERIZER_DISCARD);
4904 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
4905 }
4906
check()4907 bool gl3cts::TransformFeedback::DrawXFBFeedback::check()
4908 {
4909 /* Functions handler */
4910 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4911
4912 glw::GLfloat* results =
4913 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
4914 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
4915
4916 bool is_ok = false;
4917
4918 if (results)
4919 {
4920 if ((results[0] == 8.f) && (results[1] == 16.f) && (results[2] == 24.f) && (results[3] == 32.f))
4921 {
4922 is_ok = true;
4923 }
4924
4925 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
4926 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
4927 }
4928
4929 return is_ok;
4930 }
4931
clean()4932 void gl3cts::TransformFeedback::DrawXFBFeedback::clean()
4933 {
4934 /* Functions handler */
4935 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
4936
4937 gl.useProgram(0);
4938
4939 if (m_program_id)
4940 {
4941 gl.deleteProgram(m_program_id);
4942
4943 m_program_id = 0;
4944 }
4945
4946 if (m_xfb_id)
4947 {
4948 gl.deleteTransformFeedbacks(1, &m_xfb_id);
4949
4950 m_xfb_id = 0;
4951 }
4952
4953 for (glw::GLuint i = 0; i < s_bo_count; ++i)
4954 {
4955 if (m_bo_id[i])
4956 {
4957 gl.deleteBuffers(1, &m_bo_id[i]);
4958
4959 m_bo_id[i] = 0;
4960 }
4961 }
4962
4963 for (glw::GLuint i = 0; i < s_bo_count; ++i)
4964 {
4965 if (m_vao_id[i])
4966 {
4967 gl.deleteVertexArrays(1, &m_vao_id[i]);
4968
4969 m_vao_id[i] = 0;
4970 }
4971 }
4972 }
4973
4974 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_vertex_shader = "#version 130\n"
4975 "\n"
4976 "in vec4 position;\n"
4977 "\n"
4978 "void main()\n"
4979 "{\n"
4980 " gl_Position = position * 2.0;\n"
4981 "}\n";
4982
4983 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_fragment_shader = "#version 130\n"
4984 "\n"
4985 "out vec4 pixel;\n"
4986 "\n"
4987 "void main()\n"
4988 "{\n"
4989 " pixel = vec4(1.0);\n"
4990 "}\n";
4991
4992 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_xfb_varying = "gl_Position";
4993
4994 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBFeedback::s_attrib = "position";
4995
4996 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBFeedback::s_initial_data[] = { 1.f, 2.f, 3.f, 4.f };
4997
4998 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_draw_vertex_count =
4999 sizeof(s_initial_data) / sizeof(s_initial_data[0]) / 4 /* components */;
5000
5001 const glw::GLuint gl3cts::TransformFeedback::DrawXFBFeedback::s_bo_size = sizeof(s_initial_data);
5002
5003 /*-----------------------------------------------------------------------------------------------*/
5004
CaptureSpecialInterleaved(deqp::Context & context,const char * test_name,const char * test_description)5005 gl3cts::TransformFeedback::CaptureSpecialInterleaved::CaptureSpecialInterleaved(deqp::Context& context,
5006 const char* test_name,
5007 const char* test_description)
5008 : deqp::TestCase(context, test_name, test_description)
5009 , m_context(context)
5010 , m_program_id(0)
5011 , m_vao_id(0)
5012 , m_xfb_id(0)
5013 {
5014 memset(m_bo_id, 0, sizeof(m_bo_id));
5015 }
5016
~CaptureSpecialInterleaved(void)5017 gl3cts::TransformFeedback::CaptureSpecialInterleaved::~CaptureSpecialInterleaved(void)
5018 {
5019 }
5020
iterate(void)5021 tcu::TestNode::IterateResult gl3cts::TransformFeedback::CaptureSpecialInterleaved::iterate(void)
5022 {
5023 /* Initializations. */
5024 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5025 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5026
5027 bool is_ok = true;
5028 bool test_error = false;
5029
5030 /* Tests. */
5031 try
5032 {
5033 if (is_at_least_gl_40 || is_arb_tf_3)
5034 {
5035 prepareAndBind();
5036 draw();
5037
5038 is_ok = is_ok && check();
5039 }
5040 }
5041 catch (...)
5042 {
5043 is_ok = false;
5044 test_error = true;
5045 }
5046
5047 /* Clean GL objects. */
5048 clean();
5049
5050 /* Result's setup. */
5051 if (is_ok)
5052 {
5053 /* Log success. */
5054 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have passed."
5055 << tcu::TestLog::EndMessage;
5056
5057 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5058 }
5059 else
5060 {
5061 if (test_error)
5062 {
5063 /* Log error. */
5064 m_context.getTestContext().getLog() << tcu::TestLog::Message
5065 << "Capture Special Interleaved have approached error."
5066 << tcu::TestLog::EndMessage;
5067
5068 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5069 }
5070 else
5071 {
5072 /* Log fail. */
5073 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Capture Special Interleaved have failed."
5074 << tcu::TestLog::EndMessage;
5075
5076 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5077 }
5078 }
5079
5080 return STOP;
5081 }
5082
prepareAndBind()5083 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::prepareAndBind()
5084 {
5085 /* Functions handler */
5086 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5087
5088 /* Prepare programs. */
5089 m_program_id = gl3cts::TransformFeedback::Utilities::buildProgram(
5090 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader, s_fragment_shader, s_xfb_varyings,
5091 s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5092
5093 if (0 == m_program_id)
5094 {
5095 throw 0;
5096 }
5097
5098 gl.useProgram(m_program_id);
5099 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5100
5101 /* Prepare transform feedbacks. */
5102 gl.genTransformFeedbacks(1, &m_xfb_id);
5103 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5104
5105 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5106 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5107
5108 /* Create empty Vertex Array Object */
5109 gl.genVertexArrays(1, &m_vao_id);
5110 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5111
5112 gl.bindVertexArray(m_vao_id);
5113 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5114
5115 /* Prepare buffer objects. */
5116 gl.genBuffers(s_bo_ids_count, m_bo_id);
5117 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5118
5119 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5120 {
5121 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5122 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5123
5124 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5125 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5126
5127 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5128 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5129 }
5130 }
5131
draw()5132 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::draw()
5133 {
5134 /* Functions handler */
5135 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5136
5137 gl.enable(GL_RASTERIZER_DISCARD);
5138 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5139
5140 gl.beginTransformFeedback(GL_POINTS);
5141 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5142
5143 gl.drawArrays(GL_POINTS, 0, 1);
5144 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5145
5146 gl.endTransformFeedback();
5147 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5148
5149 gl.disable(GL_RASTERIZER_DISCARD);
5150 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5151 }
5152
check()5153 bool gl3cts::TransformFeedback::CaptureSpecialInterleaved::check()
5154 {
5155 /* Functions handler */
5156 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5157
5158 bool is_ok = true;
5159
5160 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[0]);
5161 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5162
5163 glw::GLfloat* results =
5164 (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5165 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5166
5167 if ((results[0] != 1.0) || (results[1] != 2.0) || (results[2] != 3.0) || (results[3] != 4.0) ||
5168 /* gl_SkipComponents4 here */
5169 (results[8] != 5.0) || (results[9] != 6.0) || (results[10] != 7.0) || (results[11] != 8.0))
5170 {
5171 is_ok = false;
5172 }
5173
5174 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5175 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5176
5177 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[1]);
5178 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5179
5180 results = (glw::GLfloat*)gl.mapBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, 0, s_bo_size, GL_MAP_READ_BIT);
5181 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBufferRange call failed.");
5182
5183 if ((results[0] != 9.0) || (results[1] != 10.0) || (results[2] != 11.0) || (results[3] != 12.0) ||
5184 /* gl_SkipComponents4 here */
5185 (results[8] != 13.0) || (results[9] != 14.0) || (results[10] != 15.0) || (results[11] != 16.0))
5186 {
5187 is_ok = false;
5188 }
5189
5190 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
5191 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
5192
5193 return is_ok;
5194 }
5195
clean()5196 void gl3cts::TransformFeedback::CaptureSpecialInterleaved::clean()
5197 {
5198 /* Functions handler */
5199 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5200
5201 gl.useProgram(0);
5202
5203 if (m_program_id)
5204 {
5205 gl.deleteProgram(m_program_id);
5206
5207 m_program_id = 0;
5208 }
5209
5210 if (m_xfb_id)
5211 {
5212 gl.deleteTransformFeedbacks(1, &m_xfb_id);
5213
5214 m_xfb_id = 0;
5215 }
5216
5217 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5218 {
5219 if (m_bo_id[i])
5220 {
5221 gl.deleteBuffers(1, &m_bo_id[i]);
5222
5223 m_bo_id[i] = 0;
5224 }
5225 }
5226
5227 if (m_vao_id)
5228 {
5229 gl.deleteVertexArrays(1, &m_vao_id);
5230
5231 m_vao_id = 0;
5232 }
5233 }
5234
5235 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_vertex_shader =
5236 "#version 130\n"
5237 "\n"
5238 "out vec4 variable_1;\n"
5239 "out vec4 variable_2;\n"
5240 "out vec4 variable_3;\n"
5241 "out vec4 variable_4;\n"
5242 "\n"
5243 "void main()\n"
5244 "{\n"
5245 " variable_1 = vec4(1.0, 2.0, 3.0, 4.0);\n"
5246 " variable_2 = vec4(5.0, 6.0, 7.0, 8.0);\n"
5247 " variable_3 = vec4(9.0, 10.0, 11.0, 12.0);\n"
5248 " variable_4 = vec4(13.0, 14.0, 15.0, 16.0);\n"
5249 "\n"
5250 " gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
5251 "}\n";
5252
5253 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_fragment_shader = "#version 130\n"
5254 "\n"
5255 "out vec4 pixel;\n"
5256 "\n"
5257 "void main()\n"
5258 "{\n"
5259 " pixel = vec4(1.0);\n"
5260 "}\n";
5261
5262 const glw::GLchar* gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings[] =
5263 { "variable_1", "gl_SkipComponents4", "variable_2", "gl_NextBuffer",
5264 "variable_3", "gl_SkipComponents4", "variable_4" };
5265
5266 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_xfb_varyings_count =
5267 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5268
5269 const glw::GLuint gl3cts::TransformFeedback::CaptureSpecialInterleaved::s_bo_size =
5270 3 /*number of variables / empty places */ * 4 /* vec4 */
5271 * sizeof(glw::GLfloat);
5272
5273 /*-----------------------------------------------------------------------------------------------*/
5274
DrawXFBStream(deqp::Context & context,const char * test_name,const char * test_description)5275 gl3cts::TransformFeedback::DrawXFBStream::DrawXFBStream(deqp::Context& context, const char* test_name,
5276 const char* test_description)
5277 : deqp::TestCase(context, test_name, test_description)
5278 , m_context(context)
5279 , m_program_id_generate(0)
5280 , m_program_id_draw(0)
5281 , m_vao_id(0)
5282 , m_xfb_id(0)
5283 , m_fbo_id(0)
5284 , m_rbo_id(0)
5285 {
5286 memset(m_bo_id, 0, sizeof(m_bo_id));
5287 memset(m_qo_id, 0, sizeof(m_qo_id));
5288 }
5289
~DrawXFBStream(void)5290 gl3cts::TransformFeedback::DrawXFBStream::~DrawXFBStream(void)
5291 {
5292 }
5293
iterate(void)5294 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStream::iterate(void)
5295 {
5296 /* Functions handler */
5297 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5298
5299 /* Initializations. */
5300 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
5301 bool is_arb_tf_3 = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3");
5302 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
5303
5304 glw::GLint max_vertex_streams = 0;
5305
5306 bool is_ok = true;
5307 bool test_error = false;
5308
5309 /* Tests. */
5310 try
5311 {
5312 if (is_at_least_gl_40 || (is_arb_tf_3 && is_arb_gpu_shader5))
5313 {
5314 gl.getIntegerv(GL_MAX_VERTEX_STREAMS, &max_vertex_streams);
5315 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetIntegerv call failed.");
5316
5317 if (max_vertex_streams >= 2)
5318 {
5319 prepareObjects();
5320
5321 useProgram(m_program_id_generate);
5322
5323 drawForXFB();
5324
5325 is_ok = is_ok && inspectQueries();
5326
5327 useProgram(m_program_id_draw);
5328
5329 setupVertexArray(m_bo_id[0]);
5330
5331 drawForFramebuffer(0);
5332
5333 setupVertexArray(m_bo_id[1]);
5334
5335 drawForFramebuffer(1);
5336
5337 is_ok = is_ok && check();
5338 }
5339 }
5340 }
5341 catch (...)
5342 {
5343 is_ok = false;
5344 test_error = true;
5345 }
5346
5347 /* Clean GL objects. */
5348 clean();
5349
5350 /* Result's setup. */
5351 if (is_ok)
5352 {
5353 /* Log success. */
5354 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have passed."
5355 << tcu::TestLog::EndMessage;
5356
5357 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5358 }
5359 else
5360 {
5361 if (test_error)
5362 {
5363 /* Log error. */
5364 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have approached error."
5365 << tcu::TestLog::EndMessage;
5366
5367 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5368 }
5369 else
5370 {
5371 /* Log fail. */
5372 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream have failed."
5373 << tcu::TestLog::EndMessage;
5374
5375 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5376 }
5377 }
5378
5379 return STOP;
5380 }
5381
prepareObjects()5382 void gl3cts::TransformFeedback::DrawXFBStream::prepareObjects()
5383 {
5384 /* Functions handler */
5385 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5386
5387 /* Prepare programs. */
5388 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5389 gl, m_context.getTestContext().getLog(), s_geometry_shader, NULL, NULL, s_vertex_shader_blank,
5390 s_fragment_shader, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
5391
5392 if (0 == m_program_id_generate)
5393 {
5394 throw 0;
5395 }
5396
5397 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5398 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_pass, s_fragment_shader, NULL, 0,
5399 GL_INTERLEAVED_ATTRIBS);
5400
5401 if (0 == m_program_id_draw)
5402 {
5403 throw 0;
5404 }
5405
5406 /* Prepare transform feedbacks. */
5407 gl.genTransformFeedbacks(1, &m_xfb_id);
5408 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5409
5410 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5411 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5412
5413 /* Create empty Vertex Array Object */
5414 gl.genVertexArrays(1, &m_vao_id);
5415 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5416
5417 gl.bindVertexArray(m_vao_id);
5418 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5419
5420 /* Prepare buffer objects. */
5421 gl.genBuffers(s_bo_ids_count, m_bo_id);
5422 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5423
5424 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5425 {
5426 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id[i]);
5427 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5428
5429 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5430 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5431
5432 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_bo_id[i]);
5433 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5434 }
5435
5436 /* Generate queries */
5437 gl.genQueries(s_qo_ids_count, m_qo_id);
5438 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries call failed.");
5439
5440 /* Prepare framebuffer. */
5441 gl.clearColor(0.f, 0.f, 0.f, 1.f);
5442 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5443
5444 gl.genFramebuffers(1, &m_fbo_id);
5445 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5446
5447 gl.genRenderbuffers(1, &m_rbo_id);
5448 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5449
5450 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5451 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5452
5453 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5454 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5455
5456 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5457 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5458
5459 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5460 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5461
5462 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5463 {
5464 throw 0;
5465 }
5466
5467 gl.viewport(0, 0, s_view_size, s_view_size);
5468 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5469 }
5470
setupVertexArray(glw::GLuint bo_id)5471 void gl3cts::TransformFeedback::DrawXFBStream::setupVertexArray(glw::GLuint bo_id)
5472 {
5473 /* Functions handler */
5474 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5475
5476 gl.bindBuffer(GL_ARRAY_BUFFER, bo_id);
5477 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5478
5479 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5480 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5481
5482 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5483 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5484
5485 gl.enableVertexAttribArray(position_location);
5486 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5487 }
5488
useProgram(glw::GLuint program_id)5489 void gl3cts::TransformFeedback::DrawXFBStream::useProgram(glw::GLuint program_id)
5490 {
5491 /* Functions handler */
5492 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5493
5494 gl.useProgram(program_id);
5495 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5496 }
5497
drawForXFB()5498 void gl3cts::TransformFeedback::DrawXFBStream::drawForXFB()
5499 {
5500 /* Functions handler */
5501 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5502
5503 gl.enable(GL_RASTERIZER_DISCARD);
5504 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5505
5506 gl.beginTransformFeedback(GL_POINTS);
5507 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5508
5509 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 0, m_qo_id[0]);
5510 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5511
5512 gl.beginQueryIndexed(GL_PRIMITIVES_GENERATED, 1, m_qo_id[1]);
5513 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5514
5515 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0, m_qo_id[2]);
5516 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5517
5518 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1, m_qo_id[3]);
5519 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginQueryIndexed call failed.");
5520
5521 gl.drawArrays(GL_POINTS, 0, 1);
5522 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5523
5524 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 0);
5525 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5526
5527 gl.endQueryIndexed(GL_PRIMITIVES_GENERATED, 1);
5528 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5529
5530 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 0);
5531 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5532
5533 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN, 1);
5534 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndQueryIndexed call failed.");
5535
5536 gl.endTransformFeedback();
5537 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5538
5539 gl.disable(GL_RASTERIZER_DISCARD);
5540 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5541 }
5542
drawForFramebuffer(glw::GLuint stream)5543 void gl3cts::TransformFeedback::DrawXFBStream::drawForFramebuffer(glw::GLuint stream)
5544 {
5545 /* Functions handler */
5546 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5547
5548 gl.drawTransformFeedbackStream(GL_TRIANGLES, m_xfb_id, stream);
5549 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawTransformFeedbackStream call failed.");
5550 }
5551
inspectQueries()5552 bool gl3cts::TransformFeedback::DrawXFBStream::inspectQueries()
5553 {
5554 /* Functions handler */
5555 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5556
5557 glw::GLint generated_primitives_to_stream_0 = 0;
5558 glw::GLint generated_primitives_to_stream_1 = 0;
5559
5560 gl.getQueryObjectiv(m_qo_id[0], GL_QUERY_RESULT, &generated_primitives_to_stream_0);
5561 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5562
5563 gl.getQueryObjectiv(m_qo_id[1], GL_QUERY_RESULT, &generated_primitives_to_stream_1);
5564 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5565
5566 glw::GLint primitives_written_to_xfb_to_stream_0 = 0;
5567 glw::GLint primitives_written_to_xfb_to_stream_1 = 0;
5568
5569 gl.getQueryObjectiv(m_qo_id[2], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_0);
5570 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5571
5572 gl.getQueryObjectiv(m_qo_id[3], GL_QUERY_RESULT, &primitives_written_to_xfb_to_stream_1);
5573 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryIndexediv call failed.");
5574
5575 if ((generated_primitives_to_stream_0 == 3) && (generated_primitives_to_stream_1 == 3) &&
5576 (primitives_written_to_xfb_to_stream_0 == 3) && (primitives_written_to_xfb_to_stream_1 == 3))
5577 {
5578 return true;
5579 }
5580
5581 return false;
5582 }
5583
check()5584 bool gl3cts::TransformFeedback::DrawXFBStream::check()
5585 {
5586 /* Functions handler */
5587 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5588
5589 /* Number of pixels. */
5590 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5591
5592 /* Fetch framebuffer. */
5593 std::vector<glw::GLfloat> pixels(number_of_pixels);
5594
5595 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
5596 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
5597
5598 /* Check results. */
5599 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
5600 {
5601 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
5602 {
5603 return false;
5604 }
5605 }
5606
5607 return true;
5608 }
5609
clean()5610 void gl3cts::TransformFeedback::DrawXFBStream::clean()
5611 {
5612 /* Functions handler */
5613 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5614
5615 gl.useProgram(0);
5616
5617 if (m_program_id_generate)
5618 {
5619 gl.deleteProgram(m_program_id_generate);
5620
5621 m_program_id_generate = 0;
5622 }
5623
5624 if (m_program_id_draw)
5625 {
5626 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5627
5628 gl.disableVertexAttribArray(position_location);
5629
5630 gl.deleteProgram(m_program_id_draw);
5631
5632 m_program_id_draw = 0;
5633 }
5634
5635 if (m_xfb_id)
5636 {
5637 gl.deleteTransformFeedbacks(1, &m_xfb_id);
5638
5639 m_xfb_id = 0;
5640 }
5641
5642 for (glw::GLuint i = 0; i < s_bo_ids_count; ++i)
5643 {
5644 if (m_bo_id[i])
5645 {
5646 gl.deleteBuffers(1, &m_bo_id[i]);
5647
5648 m_bo_id[i] = 0;
5649 }
5650 }
5651
5652 if (m_vao_id)
5653 {
5654 gl.deleteVertexArrays(1, &m_vao_id);
5655
5656 m_vao_id = 0;
5657 }
5658
5659 if (m_fbo_id)
5660 {
5661 gl.deleteFramebuffers(1, &m_fbo_id);
5662
5663 m_fbo_id = 0;
5664 }
5665
5666 if (m_rbo_id)
5667 {
5668 gl.deleteRenderbuffers(1, &m_rbo_id);
5669
5670 m_rbo_id = 0;
5671 }
5672 }
5673
5674 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_blank = "#version 130\n"
5675 "\n"
5676 "void main()\n"
5677 "{\n"
5678 "}\n";
5679
5680 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_vertex_shader_pass = "#version 130\n"
5681 "\n"
5682 "in vec4 position;\n"
5683 "\n"
5684 "void main()\n"
5685 "{\n"
5686 " gl_Position = position;\n"
5687 "}\n";
5688
5689 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_geometry_shader =
5690 "#version 400\n"
5691 "\n"
5692 "layout(points) in;\n"
5693 "layout(points, max_vertices = 6) out;\n"
5694 "\n"
5695 "layout(stream = 1) out vec4 position;\n"
5696 "\n"
5697 "void main()\n"
5698 "{\n"
5699 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
5700 " EmitStreamVertex(0);\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 "\n"
5706 " position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
5707 " EmitStreamVertex(1);\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 "}\n";
5713
5714 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_fragment_shader = "#version 130\n"
5715 "\n"
5716 "out vec4 pixel;\n"
5717 "\n"
5718 "void main()\n"
5719 "{\n"
5720 " pixel = vec4(1.0);\n"
5721 "}\n";
5722
5723 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings[] = { "gl_Position", "gl_NextBuffer",
5724 "position" };
5725
5726 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_xfb_varyings_count =
5727 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
5728
5729 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_bo_size =
5730 3 /* triangles */ * 4 /* vec4 */ * sizeof(glw::GLfloat);
5731
5732 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStream::s_view_size = 2;
5733
5734 /*-----------------------------------------------------------------------------------------------*/
5735
DrawXFBInstanced(deqp::Context & context,const char * test_name,const char * test_description)5736 gl3cts::TransformFeedback::DrawXFBInstanced::DrawXFBInstanced(deqp::Context& context, const char* test_name,
5737 const char* test_description)
5738 : deqp::TestCase(context, test_name, test_description)
5739 , m_context(context)
5740 , m_program_id_generate(0)
5741 , m_program_id_draw(0)
5742 , m_vao_id(0)
5743 , m_xfb_id(0)
5744 , m_bo_id_xfb(0)
5745 , m_bo_id_uniform(0)
5746 , m_fbo_id(0)
5747 , m_rbo_id(0)
5748 , m_glGetUniformBlockIndex(DE_NULL)
5749 , m_glUniformBlockBinding(DE_NULL)
5750 {
5751 }
5752
~DrawXFBInstanced(void)5753 gl3cts::TransformFeedback::DrawXFBInstanced::~DrawXFBInstanced(void)
5754 {
5755 }
5756
iterate(void)5757 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBInstanced::iterate(void)
5758 {
5759 /* Initializations. */
5760 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
5761 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
5762 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
5763 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
5764
5765 bool is_ok = true;
5766 bool test_error = false;
5767
5768 if (is_arb_ubo)
5769 {
5770 m_glGetUniformBlockIndex =
5771 (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
5772
5773 m_glUniformBlockBinding =
5774 (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
5775
5776 if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
5777 {
5778 throw 0;
5779 }
5780 }
5781
5782 try
5783 {
5784 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_tf_instanced))
5785 {
5786 prepareObjects();
5787 drawForXFB();
5788 drawInstanced();
5789
5790 is_ok = is_ok && check();
5791 }
5792 }
5793 catch (...)
5794 {
5795 is_ok = false;
5796 test_error = true;
5797 }
5798
5799 /* Clean GL objects */
5800 clean();
5801
5802 /* Result's setup. */
5803 if (is_ok)
5804 {
5805 /* Log success. */
5806 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have passed."
5807 << tcu::TestLog::EndMessage;
5808
5809 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
5810 }
5811 else
5812 {
5813 if (test_error)
5814 {
5815 /* Log error. */
5816 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have approached error."
5817 << tcu::TestLog::EndMessage;
5818
5819 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
5820 }
5821 else
5822 {
5823 /* Log fail. */
5824 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Instanced have failed."
5825 << tcu::TestLog::EndMessage;
5826
5827 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
5828 }
5829 }
5830
5831 return STOP;
5832 }
5833
prepareObjects()5834 void gl3cts::TransformFeedback::DrawXFBInstanced::prepareObjects()
5835 {
5836 /* Functions handler */
5837 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5838
5839 /* Prepare programs. */
5840 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
5841 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_generate, s_fragment_shader,
5842 &s_xfb_varying, 1, GL_INTERLEAVED_ATTRIBS);
5843
5844 if (0 == m_program_id_generate)
5845 {
5846 throw 0;
5847 }
5848
5849 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
5850 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader, NULL, 0,
5851 GL_INTERLEAVED_ATTRIBS);
5852
5853 if (0 == m_program_id_draw)
5854 {
5855 throw 0;
5856 }
5857
5858 /* Prepare transform feedbacks. */
5859 gl.genTransformFeedbacks(1, &m_xfb_id);
5860 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
5861
5862 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
5863 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
5864
5865 /* Create empty Vertex Array Object */
5866 gl.genVertexArrays(1, &m_vao_id);
5867 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
5868
5869 gl.bindVertexArray(m_vao_id);
5870 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
5871
5872 /* Prepare xfb buffer object. */
5873 gl.genBuffers(1, &m_bo_id_xfb);
5874 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5875
5876 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb);
5877 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5878
5879 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
5880 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5881
5882 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb);
5883 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5884
5885 /* Prepare uniform buffer object. */
5886 gl.genBuffers(1, &m_bo_id_uniform);
5887 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
5888
5889 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
5890 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5891
5892 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
5893 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
5894
5895 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
5896 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
5897
5898 glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
5899 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
5900
5901 if (GL_INVALID_INDEX == uniform_index)
5902 {
5903 throw 0;
5904 }
5905
5906 m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
5907 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
5908
5909 /* Prepare framebuffer. */
5910 gl.clearColor(0.f, 0.f, 0.f, 1.f);
5911 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
5912
5913 gl.genFramebuffers(1, &m_fbo_id);
5914 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
5915
5916 gl.genRenderbuffers(1, &m_rbo_id);
5917 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
5918
5919 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
5920 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
5921
5922 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
5923 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
5924
5925 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
5926 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
5927
5928 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
5929 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
5930
5931 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
5932 {
5933 throw 0;
5934 }
5935
5936 gl.viewport(0, 0, s_view_size, s_view_size);
5937 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
5938 }
5939
drawForXFB()5940 void gl3cts::TransformFeedback::DrawXFBInstanced::drawForXFB()
5941 {
5942 /* Functions handler */
5943 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5944
5945 gl.useProgram(m_program_id_generate);
5946 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5947
5948 gl.enable(GL_RASTERIZER_DISCARD);
5949 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
5950
5951 gl.beginTransformFeedback(GL_POINTS);
5952 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
5953
5954 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
5955 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5956
5957 gl.endTransformFeedback();
5958 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
5959
5960 gl.disable(GL_RASTERIZER_DISCARD);
5961 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
5962 }
5963
drawInstanced()5964 void gl3cts::TransformFeedback::DrawXFBInstanced::drawInstanced()
5965 {
5966 /* Functions handler */
5967 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5968
5969 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb);
5970 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
5971
5972 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
5973 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
5974
5975 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
5976 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
5977
5978 gl.enableVertexAttribArray(position_location);
5979 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
5980
5981 gl.clear(GL_COLOR_BUFFER_BIT);
5982 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
5983
5984 gl.useProgram(m_program_id_draw);
5985 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
5986
5987 gl.drawTransformFeedbackInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 4);
5988 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
5989 }
5990
check()5991 bool gl3cts::TransformFeedback::DrawXFBInstanced::check()
5992 {
5993 /* Functions handler */
5994 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
5995
5996 /* Number of pixels. */
5997 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
5998
5999 /* Fetch framebuffer. */
6000 std::vector<glw::GLfloat> pixels(number_of_pixels);
6001
6002 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6003 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6004
6005 /* Check results. */
6006 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6007 {
6008 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6009 {
6010 return false;
6011 }
6012 }
6013
6014 return true;
6015 }
6016
clean()6017 void gl3cts::TransformFeedback::DrawXFBInstanced::clean()
6018 {
6019 /* Functions handler */
6020 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6021
6022 gl.useProgram(0);
6023
6024 if (m_program_id_generate)
6025 {
6026 gl.deleteProgram(m_program_id_generate);
6027
6028 m_program_id_generate = 0;
6029 }
6030
6031 if (m_program_id_draw)
6032 {
6033 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6034
6035 gl.disableVertexAttribArray(position_location);
6036
6037 gl.deleteProgram(m_program_id_draw);
6038
6039 m_program_id_draw = 0;
6040 }
6041
6042 if (m_xfb_id)
6043 {
6044 gl.deleteTransformFeedbacks(1, &m_xfb_id);
6045
6046 m_xfb_id = 0;
6047 }
6048
6049 if (m_bo_id_xfb)
6050 {
6051 gl.deleteBuffers(1, &m_bo_id_xfb);
6052
6053 m_bo_id_xfb = 0;
6054 }
6055
6056 if (m_bo_id_uniform)
6057 {
6058 gl.deleteBuffers(1, &m_bo_id_uniform);
6059
6060 m_bo_id_uniform = 0;
6061 }
6062
6063 if (m_vao_id)
6064 {
6065 gl.deleteVertexArrays(1, &m_vao_id);
6066
6067 m_vao_id = 0;
6068 }
6069
6070 if (m_fbo_id)
6071 {
6072 gl.deleteFramebuffers(1, &m_fbo_id);
6073
6074 m_fbo_id = 0;
6075 }
6076
6077 if (m_rbo_id)
6078 {
6079 gl.deleteRenderbuffers(1, &m_rbo_id);
6080
6081 m_rbo_id = 0;
6082 }
6083 }
6084
6085 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_generate =
6086 "#version 140\n"
6087 "\n"
6088 "void main()\n"
6089 "{\n"
6090 " switch(gl_VertexID % 4)\n"
6091 " {\n"
6092 " case 0:\n"
6093 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6094 " break;\n"
6095 " case 1:\n"
6096 " gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
6097 " break;\n"
6098 " case 2:\n"
6099 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
6100 " break;\n"
6101 " case 3:\n"
6102 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
6103 " break;\n"
6104 " }\n"
6105 "}\n";
6106
6107 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_vertex_shader_draw =
6108 "#version 140\n"
6109 "\n"
6110 "uniform MatrixBlock\n"
6111 "{\n"
6112 " mat4 transformation_0;\n"
6113 " mat4 transformation_1;\n"
6114 " mat4 transformation_2;\n"
6115 " mat4 transformation_3;\n"
6116 "};\n"
6117 "\n"
6118 "in vec4 position;\n"
6119 "\n"
6120 "void main()\n"
6121 "{\n"
6122 " switch(gl_InstanceID % 4)\n"
6123 " {\n"
6124 " case 0:\n"
6125 " gl_Position = position * transformation_0;\n"
6126 " break;\n"
6127 " case 1:\n"
6128 " gl_Position = position * transformation_1;\n"
6129 " break;\n"
6130 " case 2:\n"
6131 " gl_Position = position * transformation_2;\n"
6132 " break;\n"
6133 " case 3:\n"
6134 " gl_Position = position * transformation_3;\n"
6135 " break;\n"
6136 " }\n"
6137 "}\n";
6138
6139 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_fragment_shader = "#version 130\n"
6140 "\n"
6141 "out vec4 pixel;\n"
6142 "\n"
6143 "void main()\n"
6144 "{\n"
6145 " pixel = vec4(1.0);\n"
6146 "}\n";
6147
6148 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_xfb_varying = "gl_Position";
6149
6150 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBInstanced::s_uniform = "MatrixBlock";
6151
6152 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_xfb_size =
6153 4 /* vertex count */ * 4 /* vec4 components */
6154 * sizeof(glw::GLfloat) /* data type size */;
6155
6156 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_data[] = {
6157 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,
6158
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
6166 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6167
6168 const glw::GLuint gl3cts::TransformFeedback::DrawXFBInstanced::s_view_size = 4;
6169
6170 /*-----------------------------------------------------------------------------------------------*/
6171
DrawXFBStreamInstanced(deqp::Context & context,const char * test_name,const char * test_description)6172 gl3cts::TransformFeedback::DrawXFBStreamInstanced::DrawXFBStreamInstanced(deqp::Context& context, const char* test_name,
6173 const char* test_description)
6174 : deqp::TestCase(context, test_name, test_description)
6175 , m_context(context)
6176 , m_program_id_generate(0)
6177 , m_program_id_draw(0)
6178 , m_vao_id(0)
6179 , m_xfb_id(0)
6180 , m_bo_id_xfb_position(0)
6181 , m_bo_id_xfb_color(0)
6182 , m_bo_id_uniform(0)
6183 , m_fbo_id(0)
6184 , m_rbo_id(0)
6185 , m_glGetUniformBlockIndex(DE_NULL)
6186 , m_glUniformBlockBinding(DE_NULL)
6187 {
6188 }
6189
~DrawXFBStreamInstanced(void)6190 gl3cts::TransformFeedback::DrawXFBStreamInstanced::~DrawXFBStreamInstanced(void)
6191 {
6192 }
6193
iterate(void)6194 tcu::TestNode::IterateResult gl3cts::TransformFeedback::DrawXFBStreamInstanced::iterate(void)
6195 {
6196 /* Initializations. */
6197 bool is_at_least_gl_31 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(3, 1)));
6198 bool is_at_least_gl_40 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 0)));
6199 bool is_at_least_gl_42 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 2)));
6200 bool is_arb_tf_instanced = m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_instanced");
6201 bool is_arb_ubo = m_context.getContextInfo().isExtensionSupported("GL_ARB_uniform_buffer_object");
6202 bool is_arb_gpu_shader5 = m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5");
6203
6204 bool is_ok = true;
6205 bool test_error = false;
6206
6207 if (is_arb_ubo)
6208 {
6209 m_glGetUniformBlockIndex =
6210 (GetUniformBlockIndex_ProcAddress)m_context.getRenderContext().getProcAddress("glGetUniformBlockIndex");
6211
6212 m_glUniformBlockBinding =
6213 (UniformBlockBinding_ProcAddress)m_context.getRenderContext().getProcAddress("glUniformBlockBinding");
6214
6215 if (DE_NULL == m_glGetUniformBlockIndex || DE_NULL == m_glUniformBlockBinding)
6216 {
6217 throw 0;
6218 }
6219 }
6220
6221 /* Test. */
6222 try
6223 {
6224 if (is_at_least_gl_42 || ((is_at_least_gl_31 || is_arb_ubo) && is_arb_gpu_shader5 && is_arb_tf_instanced) ||
6225 (is_at_least_gl_40 && is_arb_tf_instanced))
6226 {
6227 prepareObjects();
6228 drawForXFB();
6229 drawStreamInstanced();
6230
6231 is_ok = is_ok && check();
6232 }
6233 }
6234 catch (...)
6235 {
6236 is_ok = false;
6237 test_error = true;
6238 }
6239
6240 /* Clean GL objects */
6241 clean();
6242
6243 /* Result's setup. */
6244 if (is_ok)
6245 {
6246 /* Log success. */
6247 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have passed."
6248 << tcu::TestLog::EndMessage;
6249
6250 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
6251 }
6252 else
6253 {
6254 if (test_error)
6255 {
6256 /* Log error. */
6257 m_context.getTestContext().getLog() << tcu::TestLog::Message
6258 << "Draw XFB Stream Instanced have approached error."
6259 << tcu::TestLog::EndMessage;
6260
6261 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
6262 }
6263 else
6264 {
6265 /* Log fail. */
6266 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Draw XFB Stream Instanced have failed."
6267 << tcu::TestLog::EndMessage;
6268
6269 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
6270 }
6271 }
6272
6273 return STOP;
6274 }
6275
prepareObjects()6276 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::prepareObjects()
6277 {
6278 /* Functions handler */
6279 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6280
6281 /* Prepare programs. */
6282 m_program_id_generate = gl3cts::TransformFeedback::Utilities::buildProgram(
6283 gl, m_context.getTestContext().getLog(), s_geometry_shader_generate, NULL, NULL, s_vertex_shader_blank,
6284 s_fragment_shader_blank, s_xfb_varyings, s_xfb_varyings_count, GL_INTERLEAVED_ATTRIBS);
6285
6286 if (0 == m_program_id_generate)
6287 {
6288 throw 0;
6289 }
6290
6291 m_program_id_draw = gl3cts::TransformFeedback::Utilities::buildProgram(
6292 gl, m_context.getTestContext().getLog(), NULL, NULL, NULL, s_vertex_shader_draw, s_fragment_shader_draw, NULL,
6293 0, GL_INTERLEAVED_ATTRIBS);
6294
6295 if (0 == m_program_id_draw)
6296 {
6297 throw 0;
6298 }
6299
6300 /* Prepare transform feedbacks. */
6301 gl.genTransformFeedbacks(1, &m_xfb_id);
6302 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTransformFeedbacks call failed.");
6303
6304 gl.bindTransformFeedback(GL_TRANSFORM_FEEDBACK, m_xfb_id);
6305 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTransformFeedbacks call failed.");
6306
6307 /* Create empty Vertex Array Object */
6308 gl.genVertexArrays(1, &m_vao_id);
6309 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays call failed.");
6310
6311 gl.bindVertexArray(m_vao_id);
6312 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray call failed.");
6313
6314 /* Prepare xfb buffer objects. */
6315 gl.genBuffers(1, &m_bo_id_xfb_position);
6316 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6317
6318 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_position);
6319 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6320
6321 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6322 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6323
6324 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_id_xfb_position);
6325 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6326
6327 gl.genBuffers(1, &m_bo_id_xfb_color);
6328 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6329
6330 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_id_xfb_color);
6331 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6332
6333 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, s_bo_xfb_size, NULL, GL_DYNAMIC_COPY); /* allocation */
6334 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6335
6336 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 1, m_bo_id_xfb_color);
6337 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6338
6339 /* Prepare uniform buffer object. */
6340 gl.genBuffers(1, &m_bo_id_uniform);
6341 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers call failed.");
6342
6343 gl.bindBuffer(GL_UNIFORM_BUFFER, m_bo_id_uniform);
6344 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6345
6346 gl.bufferData(GL_UNIFORM_BUFFER, s_bo_uniform_size, s_bo_uniform_data, GL_DYNAMIC_COPY); /* allocation */
6347 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData call failed.");
6348
6349 gl.bindBufferBase(GL_UNIFORM_BUFFER, 0, m_bo_id_uniform);
6350 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferRange call failed.");
6351
6352 glw::GLuint uniform_index = m_glGetUniformBlockIndex(m_program_id_draw, s_uniform);
6353 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetUniformBlockIndex call failed.");
6354
6355 if (GL_INVALID_INDEX == uniform_index)
6356 {
6357 throw 0;
6358 }
6359
6360 m_glUniformBlockBinding(m_program_id_draw, uniform_index, 0);
6361 GLU_EXPECT_NO_ERROR(gl.getError(), "glUniformBlockBinding call failed.");
6362
6363 /* Prepare framebuffer. */
6364 gl.clearColor(0.f, 0.f, 0.f, 1.f);
6365 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
6366
6367 gl.genFramebuffers(1, &m_fbo_id);
6368 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
6369
6370 gl.genRenderbuffers(1, &m_rbo_id);
6371 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
6372
6373 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo_id);
6374 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
6375
6376 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo_id);
6377 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
6378
6379 gl.renderbufferStorage(GL_RENDERBUFFER, GL_R8, s_view_size, s_view_size);
6380 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
6381
6382 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo_id);
6383 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
6384
6385 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
6386 {
6387 throw 0;
6388 }
6389
6390 gl.viewport(0, 0, s_view_size, s_view_size);
6391 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
6392 }
6393
drawForXFB()6394 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawForXFB()
6395 {
6396 /* Functions handler */
6397 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6398
6399 gl.useProgram(m_program_id_generate);
6400 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6401
6402 gl.enable(GL_RASTERIZER_DISCARD);
6403 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnable call failed.");
6404
6405 gl.beginTransformFeedback(GL_POINTS);
6406 GLU_EXPECT_NO_ERROR(gl.getError(), "glBeginTransformFeedback call failed.");
6407
6408 gl.drawArrays(GL_POINTS, 0, 4 /* quad vertex count */);
6409 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6410
6411 gl.endTransformFeedback();
6412 GLU_EXPECT_NO_ERROR(gl.getError(), "glEndTransformFeedback call failed.");
6413
6414 gl.disable(GL_RASTERIZER_DISCARD);
6415 GLU_EXPECT_NO_ERROR(gl.getError(), "glDisable call failed.");
6416 }
6417
drawStreamInstanced()6418 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::drawStreamInstanced()
6419 {
6420 /* Functions handler */
6421 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6422
6423 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_position);
6424 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6425
6426 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6427 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6428
6429 gl.vertexAttribPointer(position_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6430 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6431
6432 gl.enableVertexAttribArray(position_location);
6433 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6434
6435 gl.bindBuffer(GL_ARRAY_BUFFER, m_bo_id_xfb_color);
6436 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer call failed.");
6437
6438 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6439 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetAttribLocation call failed.");
6440
6441 gl.vertexAttribPointer(color_location, 4, GL_FLOAT, GL_FALSE, 0, NULL);
6442 GLU_EXPECT_NO_ERROR(gl.getError(), "glVertexAttribPointer call failed.");
6443
6444 gl.enableVertexAttribArray(color_location);
6445 GLU_EXPECT_NO_ERROR(gl.getError(), "glEnableVertexAttribArray call failed.");
6446
6447 gl.useProgram(m_program_id_draw);
6448 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
6449
6450 gl.drawTransformFeedbackStreamInstanced(GL_TRIANGLE_STRIP, m_xfb_id, 0, 4);
6451 GLU_EXPECT_NO_ERROR(gl.getError(), "glDrawArrays call failed.");
6452 }
6453
check()6454 bool gl3cts::TransformFeedback::DrawXFBStreamInstanced::check()
6455 {
6456 /* Functions handler */
6457 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6458
6459 /* Number of pixels. */
6460 const glw::GLuint number_of_pixels = s_view_size * s_view_size;
6461
6462 /* Fetch framebuffer. */
6463 std::vector<glw::GLfloat> pixels(number_of_pixels);
6464
6465 gl.readPixels(0, 0, s_view_size, s_view_size, GL_RED, GL_FLOAT, &pixels[0]);
6466 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels call failed.");
6467
6468 /* Check results. */
6469 for (glw::GLuint i = 0; i < number_of_pixels; ++i)
6470 {
6471 if (fabs(pixels[i] - 1.f) > 0.0625 /* precision, expected result == 1.0 */)
6472 {
6473 return false;
6474 }
6475 }
6476
6477 return true;
6478 }
6479
clean()6480 void gl3cts::TransformFeedback::DrawXFBStreamInstanced::clean()
6481 {
6482 /* Functions handler */
6483 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
6484
6485 gl.useProgram(0);
6486
6487 if (m_program_id_generate)
6488 {
6489 gl.deleteProgram(m_program_id_generate);
6490
6491 m_program_id_generate = 0;
6492 }
6493
6494 if (m_program_id_draw)
6495 {
6496 glw::GLuint position_location = gl.getAttribLocation(m_program_id_draw, "position");
6497
6498 gl.disableVertexAttribArray(position_location);
6499
6500 glw::GLuint color_location = gl.getAttribLocation(m_program_id_draw, "color");
6501
6502 gl.disableVertexAttribArray(color_location);
6503
6504 gl.deleteProgram(m_program_id_draw);
6505
6506 m_program_id_draw = 0;
6507 }
6508
6509 if (m_xfb_id)
6510 {
6511 gl.deleteTransformFeedbacks(1, &m_xfb_id);
6512
6513 m_xfb_id = 0;
6514 }
6515
6516 if (m_bo_id_xfb_position)
6517 {
6518 gl.deleteBuffers(1, &m_bo_id_xfb_position);
6519
6520 m_bo_id_xfb_position = 0;
6521 }
6522
6523 if (m_bo_id_xfb_color)
6524 {
6525 gl.deleteBuffers(1, &m_bo_id_xfb_color);
6526
6527 m_bo_id_xfb_position = 0;
6528 }
6529
6530 if (m_bo_id_uniform)
6531 {
6532 gl.deleteBuffers(1, &m_bo_id_uniform);
6533
6534 m_bo_id_uniform = 0;
6535 }
6536
6537 if (m_vao_id)
6538 {
6539 gl.deleteVertexArrays(1, &m_vao_id);
6540
6541 m_vao_id = 0;
6542 }
6543
6544 if (m_fbo_id)
6545 {
6546 gl.deleteFramebuffers(1, &m_fbo_id);
6547
6548 m_fbo_id = 0;
6549 }
6550
6551 if (m_rbo_id)
6552 {
6553 gl.deleteRenderbuffers(1, &m_rbo_id);
6554
6555 m_rbo_id = 0;
6556 }
6557 }
6558
6559 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_blank = "#version 140\n"
6560 "\n"
6561 "void main()\n"
6562 "{\n"
6563 "}\n";
6564
6565 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_geometry_shader_generate =
6566 "#version 400\n"
6567 "\n"
6568 "layout(points) in;\n"
6569 "layout(points, max_vertices = 8) out;\n"
6570 "\n"
6571 "layout(stream = 1) out vec4 color;\n"
6572 "\n"
6573 "void main()\n"
6574 "{\n"
6575 " gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
6576 " EmitStreamVertex(0);\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 "\n"
6584 " color = vec4(1.0, 1.0, 1.0, 1.0);\n"
6585 " EmitStreamVertex(1);\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 "}\n";
6593
6594 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_vertex_shader_draw =
6595 "#version 140\n"
6596 "\n"
6597 "uniform MatrixBlock\n"
6598 "{\n"
6599 " mat4 transformation_0;\n"
6600 " mat4 transformation_1;\n"
6601 " mat4 transformation_2;\n"
6602 " mat4 transformation_3;\n"
6603 "};\n"
6604 "\n"
6605 "in vec4 position;\n"
6606 "in vec4 color;\n"
6607 "out vec4 colour;\n"
6608 "\n"
6609 "void main()\n"
6610 "{\n"
6611 " switch(gl_InstanceID % 4)\n"
6612 " {\n"
6613 " case 0:\n"
6614 " gl_Position = position * transformation_0;\n"
6615 " break;\n"
6616 " case 1:\n"
6617 " gl_Position = position * transformation_1;\n"
6618 " break;\n"
6619 " case 2:\n"
6620 " gl_Position = position * transformation_2;\n"
6621 " break;\n"
6622 " case 3:\n"
6623 " gl_Position = position * transformation_3;\n"
6624 " break;\n"
6625 " }\n"
6626 " colour = color;\n"
6627 "}\n";
6628
6629 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_blank =
6630 "#version 130\n"
6631 "\n"
6632 "out vec4 pixel;\n"
6633 "\n"
6634 "void main()\n"
6635 "{\n"
6636 " pixel = vec4(1.0);\n"
6637 "}\n";
6638
6639 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_fragment_shader_draw = "#version 130\n"
6640 "\n"
6641 "in vec4 colour;\n"
6642 "out vec4 pixel;\n"
6643 "\n"
6644 "void main()\n"
6645 "{\n"
6646 " pixel = colour;\n"
6647 "}\n";
6648
6649 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings[] = { "gl_Position",
6650 "gl_NextBuffer", "color" };
6651
6652 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_xfb_varyings_count =
6653 sizeof(s_xfb_varyings) / sizeof(s_xfb_varyings[0]);
6654
6655 const glw::GLchar* gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_uniform = "MatrixBlock";
6656
6657 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_xfb_size =
6658 4 /* vertex count */ * 4 /* vec4 components */
6659 * sizeof(glw::GLfloat) /* data type size */;
6660
6661 const glw::GLfloat gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_data[] = {
6662 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,
6663
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
6671 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_bo_uniform_size = sizeof(s_bo_uniform_data);
6672
6673 const glw::GLuint gl3cts::TransformFeedback::DrawXFBStreamInstanced::s_view_size = 4;
6674
6675 /*-----------------------------------------------------------------------------------------------*/
6676
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)6677 glw::GLuint gl3cts::TransformFeedback::Utilities::buildProgram(
6678 glw::Functions const& gl, tcu::TestLog& log, glw::GLchar const* const geometry_shader_source,
6679 glw::GLchar const* const tessellation_control_shader_source,
6680 glw::GLchar const* const tessellation_evaluation_shader_source, glw::GLchar const* const vertex_shader_source,
6681 glw::GLchar const* const fragment_shader_source, glw::GLchar const* const* const transform_feedback_varyings,
6682 glw::GLsizei const transform_feedback_varyings_count, glw::GLenum const transform_feedback_varyings_mode,
6683 bool const do_not_detach, glw::GLint* linking_status)
6684 {
6685 glw::GLuint program = 0;
6686
6687 struct Shader
6688 {
6689 glw::GLchar const* const source;
6690 glw::GLenum const type;
6691 glw::GLuint id;
6692 } shader[] = { { geometry_shader_source, GL_GEOMETRY_SHADER, 0 },
6693 { tessellation_control_shader_source, GL_TESS_CONTROL_SHADER, 0 },
6694 { tessellation_evaluation_shader_source, GL_TESS_EVALUATION_SHADER, 0 },
6695 { vertex_shader_source, GL_VERTEX_SHADER, 0 },
6696 { fragment_shader_source, GL_FRAGMENT_SHADER, 0 } };
6697
6698 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
6699
6700 try
6701 {
6702 /* Create program. */
6703 program = gl.createProgram();
6704 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
6705
6706 /* Shader compilation. */
6707
6708 for (glw::GLuint i = 0; i < shader_count; ++i)
6709 {
6710 if (DE_NULL != shader[i].source)
6711 {
6712 shader[i].id = gl.createShader(shader[i].type);
6713
6714 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
6715
6716 gl.attachShader(program, shader[i].id);
6717
6718 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
6719
6720 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
6721
6722 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
6723
6724 gl.compileShader(shader[i].id);
6725
6726 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
6727
6728 glw::GLint status = GL_FALSE;
6729
6730 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
6731 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6732
6733 if (GL_FALSE == status)
6734 {
6735 glw::GLint log_size = 0;
6736 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
6737 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
6738
6739 glw::GLchar* log_text = new glw::GLchar[log_size];
6740
6741 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
6742
6743 log << tcu::TestLog::Message << "Shader compilation has failed.\n"
6744 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
6745 << "Shader compilation error log:\n"
6746 << log_text << "\n"
6747 << "Shader source code:\n"
6748 << shader[i].source << "\n"
6749 << tcu::TestLog::EndMessage;
6750
6751 delete[] log_text;
6752
6753 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
6754
6755 throw 0;
6756 }
6757 }
6758 }
6759
6760 /* Link. */
6761 if (transform_feedback_varyings_count)
6762 {
6763 gl.transformFeedbackVaryings(program, transform_feedback_varyings_count, transform_feedback_varyings,
6764 transform_feedback_varyings_mode);
6765 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6766 }
6767
6768 gl.linkProgram(program);
6769
6770 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
6771
6772 glw::GLint status = GL_FALSE;
6773
6774 gl.getProgramiv(program, GL_LINK_STATUS, &status);
6775
6776 if (DE_NULL != linking_status)
6777 {
6778 *linking_status = status;
6779 }
6780
6781 if (GL_TRUE == status)
6782 {
6783 if (!do_not_detach)
6784 {
6785 for (glw::GLuint i = 0; i < shader_count; ++i)
6786 {
6787 if (shader[i].id)
6788 {
6789 gl.detachShader(program, shader[i].id);
6790
6791 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
6792 }
6793 }
6794 }
6795 }
6796 else
6797 {
6798 glw::GLint log_size = 0;
6799
6800 gl.getProgramiv(program, GL_INFO_LOG_LENGTH, &log_size);
6801
6802 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
6803
6804 glw::GLchar* log_text = new glw::GLchar[log_size];
6805
6806 gl.getProgramInfoLog(program, log_size, NULL, &log_text[0]);
6807
6808 log << tcu::TestLog::Message << "Program linkage has failed due to:\n"
6809 << log_text << "\n"
6810 << tcu::TestLog::EndMessage;
6811
6812 delete[] log_text;
6813
6814 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
6815
6816 throw 0;
6817 }
6818 }
6819 catch (...)
6820 {
6821 if (program)
6822 {
6823 gl.deleteProgram(program);
6824
6825 program = 0;
6826 }
6827 }
6828
6829 for (glw::GLuint i = 0; i < shader_count; ++i)
6830 {
6831 if (0 != shader[i].id)
6832 {
6833 gl.deleteShader(shader[i].id);
6834
6835 shader[i].id = 0;
6836 }
6837 }
6838
6839 return program;
6840 }
6841
6842 /** @brief Substitute key with value within source code.
6843 *
6844 * @param [in] source Source code to be prerocessed.
6845 * @param [in] key Key to be substituted.
6846 * @param [in] value Value to be inserted.
6847 *
6848 * @return Resulting string.
6849 */
preprocessCode(std::string source,std::string key,std::string value)6850 std::string gl3cts::TransformFeedback::Utilities::preprocessCode(std::string source, std::string key, std::string value)
6851 {
6852 std::string destination = source;
6853
6854 while (true)
6855 {
6856 /* Find token in source code. */
6857 size_t position = destination.find(key, 0);
6858
6859 /* No more occurences of this key. */
6860 if (position == std::string::npos)
6861 {
6862 break;
6863 }
6864
6865 /* Replace token with sub_code. */
6866 destination.replace(position, key.size(), value);
6867 }
6868
6869 return destination;
6870 }
6871
6872 /** @brief Convert an integer to a string.
6873 *
6874 * @param [in] i Integer to be converted.
6875 *
6876 * @return String representing integer.
6877 */
itoa(glw::GLint i)6878 std::string gl3cts::TransformFeedback::Utilities::itoa(glw::GLint i)
6879 {
6880 std::stringstream stream;
6881
6882 stream << i;
6883
6884 return stream.str();
6885 }
6886
6887 /** @brief Convert an float to a string.
6888 *
6889 * @param [in] f Float to be converted.
6890 *
6891 * @return String representing integer.
6892 */
ftoa(glw::GLfloat f)6893 std::string gl3cts::TransformFeedback::Utilities::ftoa(glw::GLfloat f)
6894 {
6895 std::stringstream stream;
6896
6897 stream << f;
6898
6899 return stream.str();
6900 }
6901