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