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