9adb6814c2a52f34840ecc1831da5267009d0c44
[platform/upstream/VK-GL-CTS.git] / external / openglcts / modules / gl / gl3cTransformFeedbackOverflowQueryTests.cpp
1 /*-------------------------------------------------------------------------
2  * OpenGL Conformance Test Suite
3  * -----------------------------
4  *
5  * Copyright (c) 2014-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  * \file  gl3cTransformFeedbackOverflowQueryTests.cpp
26  * \brief Implements conformance tests for "Transform Feedback Overflow
27  *        Query" functionality.
28  */ /*-------------------------------------------------------------------*/
29
30 #include "gl3cTransformFeedbackOverflowQueryTests.hpp"
31
32 #include "deMath.h"
33 #include "deSharedPtr.hpp"
34
35 #include "gluContextInfo.hpp"
36 #include "gluDefs.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluShaderProgram.hpp"
39
40 #include "tcuFuzzyImageCompare.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRenderTarget.hpp"
43 #include "tcuSurface.hpp"
44 #include "tcuTestLog.hpp"
45
46 #include "glw.h"
47 #include "glwFunctions.hpp"
48
49 namespace gl3cts
50 {
51
52 /*
53  Base class of all test cases of the feature. Enforces the requirements below:
54
55  * Check that the extension string is available.
56  */
57 class TransformFeedbackOverflowQueryBaseTest : public deqp::TestCase
58 {
59 protected:
60         TransformFeedbackOverflowQueryBaseTest(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
61                                                                                    const char* name, const char* description)
62                 : TestCase(context, name, description), m_api(api), m_max_vertex_streams(0)
63         {
64         }
65
66         /* Checks whether the feature is supported. */
67         bool featureSupported()
68         {
69                 return (m_api == TransformFeedbackOverflowQueryTests::API_GL_ARB_transform_feedback_overflow_query &&
70                                 m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback_overflow_query"));
71         }
72
73         /* Checks whether transform_feedback2 is supported. */
74         bool supportsTransformFeedback2()
75         {
76                 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback2") ||
77                                 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 0, glu::PROFILE_CORE)));
78         }
79
80         /* Checks whether transform_feedback3 is supported. */
81         bool supportsTransformFeedback3()
82         {
83                 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_transform_feedback3") ||
84                                 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 0, glu::PROFILE_CORE)));
85         }
86
87         /* Checks whether gpu_shader5 is supported. */
88         bool supportsGpuShader5()
89         {
90                 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_gpu_shader5") ||
91                                 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 0, glu::PROFILE_CORE)));
92         }
93
94         /* Checks whether conditional_render_inverted is supported. */
95         bool supportsConditionalRenderInverted()
96         {
97                 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_conditional_render_inverted") ||
98                                 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 5, glu::PROFILE_CORE)));
99         }
100
101         /* Checks whether query_buffer_object are supported. */
102         bool supportsQueryBufferObject()
103         {
104                 return (m_context.getContextInfo().isExtensionSupported("GL_ARB_query_buffer_object") ||
105                                 glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType(4, 4, glu::PROFILE_CORE)));
106         }
107
108         /* Returns the maximum number of vertex streams. */
109         GLuint getMaxVertexStreams() const
110         {
111                 return m_max_vertex_streams;
112         }
113
114         /* Basic test init, child classes must call it. */
115         virtual void init()
116         {
117                 if (!featureSupported())
118                 {
119                         throw tcu::NotSupportedError("Required transform_feedback_overflow_query extension is not supported");
120                 }
121
122                 if (supportsTransformFeedback3())
123                 {
124                         m_max_vertex_streams = (GLuint)m_context.getContextInfo().getInt(GL_MAX_VERTEX_STREAMS);
125                 }
126         }
127
128 protected:
129         const TransformFeedbackOverflowQueryTests::API m_api;
130
131 private:
132         GLuint m_max_vertex_streams;
133 };
134
135 /*
136  API Implementation Dependent State Test
137
138  * Check that calling GetQueryiv with target TRANSFORM_FEEDBACK_OVERFLOW_ARB
139  and pname QUERY_COUNTER_BITS returns a non-negative value without error.
140
141  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
142  GetQueryiv with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and pname
143  QUERY_COUNTER_BITS returns a non-negative value without error.
144  */
145 class TransformFeedbackOverflowQueryImplDepState : public TransformFeedbackOverflowQueryBaseTest
146 {
147 public:
148         TransformFeedbackOverflowQueryImplDepState(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
149                                                                                            const char* name)
150                 : TransformFeedbackOverflowQueryBaseTest(
151                           context, api, name,
152                           "Tests whether the implementation dependent state defined by the feature matches the requirements.")
153         {
154         }
155
156         /* Test case iterate function. Contains the actual test case logic. */
157         IterateResult iterate()
158         {
159                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
160                 GLint                             counterBits;
161
162                 gl.getQueryiv(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, GL_QUERY_COUNTER_BITS, &counterBits);
163                 if (counterBits < 0)
164                 {
165                         TCU_FAIL("Value of QUERY_COUNTER_BITS for query target TRANSFORM_FEEDBACK_OVERFLOW_ARB is invalid");
166                 }
167
168                 if (supportsTransformFeedback3())
169                 {
170                         gl.getQueryiv(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, GL_QUERY_COUNTER_BITS, &counterBits);
171                         if (counterBits < 0)
172                         {
173                                 TCU_FAIL(
174                                         "Value of QUERY_COUNTER_BITS for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB is invalid");
175                         }
176                 }
177
178                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
179
180                 return STOP;
181         }
182 };
183
184 /*
185  Base class for all test cases of the feature that verify newly introduced context state.
186  */
187 class TransformFeedbackOverflowQueryContextStateBase : public TransformFeedbackOverflowQueryBaseTest
188 {
189 protected:
190         TransformFeedbackOverflowQueryContextStateBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
191                                                                                                    const char* name, const char* description)
192                 : TransformFeedbackOverflowQueryBaseTest(context, api, name, description)
193         {
194         }
195
196         /* Returns whether CURRENT_QUERY state for the specified target and index matches the given value. */
197         bool verifyCurrentQueryState(GLenum target, GLuint index, GLuint value)
198         {
199                 const glw::Functions& gl           = m_context.getRenderContext().getFunctions();
200                 GLint                             expected = (GLint)value;
201                 GLint                             actual;
202
203                 // Use GetQueryIndexediv by default
204                 gl.getQueryIndexediv(target, index, GL_CURRENT_QUERY, &actual);
205                 if (actual != expected)
206                 {
207                         return false;
208                 }
209
210                 if (index == 0)
211                 {
212                         // If index is zero then GetQueryiv should also return the expected value
213                         gl.getQueryiv(target, GL_CURRENT_QUERY, &actual);
214                         if (actual != expected)
215                         {
216                                 return false;
217                         }
218                 }
219
220                 return true;
221         }
222 };
223
224 /*
225  API Default Context State Test
226
227  * Check that calling GetQueryiv with target TRANSFORM_FEEDBACK_OVERFLOW_ARB
228  and pname CURRENT_QUERY returns zero by default.
229
230  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
231  GetQueryIndexediv with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and
232  pname CURRENT_QUERY returns zero for any index between zero and MAX_-
233  VERTEX_STREAMS.
234  */
235 class TransformFeedbackOverflowQueryDefaultState : public TransformFeedbackOverflowQueryContextStateBase
236 {
237 public:
238         TransformFeedbackOverflowQueryDefaultState(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
239                                                                                            const char* name)
240                 : TransformFeedbackOverflowQueryContextStateBase(
241                           context, api, name,
242                           "Tests whether the new context state defined by the feature has the expected default values.")
243         {
244         }
245
246         /* Test case iterate function. Contains the actual test case logic. */
247         IterateResult iterate()
248         {
249                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0, 0))
250                 {
251                         TCU_FAIL("Default value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_OVERFLOW_ARB is non-zero");
252                 }
253
254                 if (supportsTransformFeedback3())
255                 {
256                         for (GLuint i = 0; i < getMaxVertexStreams(); ++i)
257                         {
258                                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, 0, 0))
259                                 {
260                                         TCU_FAIL("Default value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB "
261                                                          "is non-zero");
262                                 }
263                         }
264                 }
265
266                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
267
268                 return STOP;
269         }
270 };
271
272 /*
273  API Context State Update Test
274
275  * Check that after a successful call to BeginQuery with target TRANSFORM_-
276  FEEDBACK_OVERFLOW_ARB calling GetQueryiv with the same target and with
277  pname CURRENT_QUERY returns the name of the query previously passed to
278  BeginQuery. Also check that after calling EndQuery with the same target
279  GetQueryiv returns zero for the same parameters.
280
281  * If GL 4.0 or ARB_transform_feedback3 is supported, check that after a
282  successful call to BeginQueryIndexed with target TRANSFORM_FEEDBACK_-
283  STREAM_OVERFLOW_ARB calling GetQueryIndexediv with the same target and
284  with pname CURRENT_QUERY returns the name of the query previously passed
285  to BeginQueryIndexed if the index parameters match and otherwise it
286  returns zero. Also check that after calling EndQueryIndexed with the
287  same target and index GetQueryIndexediv returns zero for the same
288  parameters for all indices. Indices used should be between zero and
289  MAX_VERTEX_STREAMS.
290  */
291 class TransformFeedbackOverflowQueryStateUpdate : public TransformFeedbackOverflowQueryContextStateBase
292 {
293 public:
294         TransformFeedbackOverflowQueryStateUpdate(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
295                                                                                           const char* name)
296                 : TransformFeedbackOverflowQueryContextStateBase(
297                           context, api, name,
298                           "Tests whether the new context state defined by the feature is correctly updated after a successful "
299                           "call to {Begin|End}Query[Indexed] if the target of the query is one of the newly introduced ones.")
300                 , m_overflow_query(0)
301                 , m_stream_overflow_query(0)
302         {
303         }
304
305         /* Test case init. */
306         virtual void init()
307         {
308                 TransformFeedbackOverflowQueryContextStateBase::init();
309
310                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
311
312                 gl.genQueries(1, &m_overflow_query);
313                 gl.genQueries(1, &m_stream_overflow_query);
314         }
315
316         /* Test case deinit */
317         virtual void deinit()
318         {
319                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
320
321                 gl.deleteQueries(1, &m_overflow_query);
322                 gl.deleteQueries(1, &m_stream_overflow_query);
323
324                 TransformFeedbackOverflowQueryContextStateBase::deinit();
325         }
326
327         /* Test case iterate function. Contains the actual test case logic. */
328         IterateResult iterate()
329         {
330                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
331
332                 // Call BeginQuery
333                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_overflow_query);
334
335                 // Verify that CURRENT_QUERY is set to the name of the query
336                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0, m_overflow_query))
337                 {
338                         TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_OVERFLOW_ARB is not updated properly "
339                                          "after a call to BeginQuery");
340                 }
341
342                 // Call EndQuery
343                 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB);
344
345                 // Verify that CURRENT_QUERY is reset to zero
346                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0, 0))
347                 {
348                         TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_OVERFLOW_ARB is not reset properly "
349                                          "after a call to EndQuery");
350                 }
351
352                 if (supportsTransformFeedback3())
353                 {
354                         for (GLuint i = 0; i < getMaxVertexStreams(); ++i)
355                         {
356                                 // Call BeginQueryIndexed with specified index
357                                 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i, m_stream_overflow_query);
358
359                                 // Verify that CURRENT_QUERY is set to the name of the query for the specified index, but remains zero for other indices
360                                 for (GLuint j = 0; j < getMaxVertexStreams(); ++j)
361                                 {
362                                         if (i == j)
363                                         {
364                                                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, j,
365                                                                                                          m_stream_overflow_query))
366                                                 {
367                                                         TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB "
368                                                                          "is not updated properly after a call to BeginQueryIndexed");
369                                                 }
370                                         }
371                                         else
372                                         {
373                                                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, j, 0))
374                                                 {
375                                                         TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB "
376                                                                          "is incorrectly updated for an unrelated vertex stream"
377                                                                          "index after a call to BeginQueryIndexed");
378                                                 }
379                                         }
380                                 }
381
382                                 // Call EndQueryIndexed with specified index
383                                 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i);
384
385                                 // Verify that CURRENT_QUERY is reset to zero for the specified index and still remains zero for other indices
386                                 for (GLuint j = 0; j < getMaxVertexStreams(); ++j)
387                                 {
388                                         if (i == j)
389                                         {
390                                                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, j, 0))
391                                                 {
392                                                         TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB "
393                                                                          "is not reset properly after a call to EndQueryIndexed");
394                                                 }
395                                         }
396                                         else
397                                         {
398                                                 if (!verifyCurrentQueryState(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, j, 0))
399                                                 {
400                                                         TCU_FAIL("Value of CURRENT_QUERY for query target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB "
401                                                                          "is incorrectly updated for an unrelated vertex stream"
402                                                                          "index after a call to EndQueryIndexed");
403                                                 }
404                                         }
405                                 }
406                         }
407                 }
408
409                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
410
411                 return STOP;
412         }
413
414 protected:
415         GLuint m_overflow_query;
416         GLuint m_stream_overflow_query;
417 };
418
419 /*
420  Base class for all test cases of the feature that verify various error scenarios.
421  */
422 class TransformFeedbackOverflowQueryErrorBase : public TransformFeedbackOverflowQueryBaseTest
423 {
424 protected:
425         TransformFeedbackOverflowQueryErrorBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
426                                                                                         const char* name, const char* description)
427                 : TransformFeedbackOverflowQueryBaseTest(context, api, name, description), m_case_name(0)
428         {
429         }
430
431         /* Starts a new error scenario sub-test with the given name. The name is used in error messages if the sub-test fails. */
432         void startTest(const char* caseName)
433         {
434                 m_case_name = caseName;
435         }
436
437         /* Verifies whether the actually generated error matches that of the expected one. If not then it triggers the failure
438          of the test case with the sub-case name used as the failure message. */
439         void verifyError(GLenum expectedError)
440         {
441                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
442
443                 GLenum actualError = gl.getError();
444
445                 if (actualError != expectedError)
446                 {
447                         TCU_FAIL(m_case_name);
448                 }
449         }
450
451 private:
452         const char* m_case_name;
453 };
454
455 /*
456  API Invalid Index Error Test
457
458  * Check that calling GetQueryIndexediv with target TRANSFORM_FEEDBACK_-
459  OVERFLOW_ARB and a non-zero index generates an INVALID_VALUE error.
460
461  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
462  GetQueryIndexediv with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB
463  and an index greater than or equal to MAX_VERTEX_STREAMS generates an
464  INVALID_VALUE error.
465
466  * Check that calling BeginQueryIndexed with target TRANSFORM_FEEDBACK_-
467  OVERFLOW_ARB and a non-zero index generates an INVALID_VALUE error.
468
469  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
470  BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB
471  and an index greater than or equal to MAX_VERTEX_STREAMS generates an
472  INVALID_VALUE error.
473  */
474 class TransformFeedbackOverflowQueryErrorInvalidIndex : public TransformFeedbackOverflowQueryErrorBase
475 {
476 public:
477         TransformFeedbackOverflowQueryErrorInvalidIndex(deqp::Context&                                                   context,
478                                                                                                         TransformFeedbackOverflowQueryTests::API api, const char* name)
479                 : TransformFeedbackOverflowQueryErrorBase(
480                           context, api, name, "Verifies whether an INVALID_VALUE error is properly generated if GetQueryIndexediv "
481                                                                   "or BeginQueryIndexed is called "
482                                                                   "with an invalid index when using the new targets introduced by the feature.")
483                 , m_query(0)
484         {
485         }
486
487         /* Test case init. */
488         virtual void init()
489         {
490                 TransformFeedbackOverflowQueryErrorBase::init();
491
492                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
493
494                 gl.genQueries(1, &m_query);
495         }
496
497         /* Test case deinit */
498         virtual void deinit()
499         {
500                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
501
502                 gl.deleteQueries(1, &m_query);
503
504                 TransformFeedbackOverflowQueryErrorBase::deinit();
505         }
506
507         /* Test case iterate function. Contains the actual test case logic. */
508         IterateResult iterate()
509         {
510                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
511                 GLint                             value;
512
513                 startTest("GetQueryIndexediv must generate INVALID_VALUE if <target> is "
514                                   "TRANSFORM_FEEDBACK_OVERFLOW_ARB and <index> is non-zero.");
515
516                 for (GLuint i = 1; i < getMaxVertexStreams(); ++i)
517                 {
518                         gl.getQueryIndexediv(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, i, GL_CURRENT_QUERY, &value);
519                         verifyError(GL_INVALID_VALUE);
520                 }
521
522                 if (supportsTransformFeedback3())
523                 {
524                         startTest("GetQueryIndexediv must generate INVALID_VALUE if <target> is "
525                                           "TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and <index> is greater "
526                                           "than or equal to MAX_VERTEX_STREAMS.");
527
528                         for (GLuint i = getMaxVertexStreams(); i < getMaxVertexStreams() + 4; ++i)
529                         {
530                                 gl.getQueryIndexediv(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i, GL_CURRENT_QUERY, &value);
531                                 verifyError(GL_INVALID_VALUE);
532                         }
533                 }
534
535                 startTest("BeginQueryIndexed must generate INVALID_VALUE if <target> is "
536                                   "TRANSFORM_FEEDBACK_OVERFLOW_ARB and <index> is non-zero.");
537
538                 for (GLuint i = 1; i < getMaxVertexStreams(); ++i)
539                 {
540                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, i, m_query);
541                         verifyError(GL_INVALID_VALUE);
542                 }
543
544                 if (supportsTransformFeedback3())
545                 {
546                         startTest("BeginQueryIndexed must generate INVALID_VALUE if <target> is "
547                                           "TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and <index> is greater "
548                                           "than or equal to MAX_VERTEX_STREAMS.");
549
550                         for (GLuint i = getMaxVertexStreams(); i < getMaxVertexStreams() + 4; ++i)
551                         {
552                                 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i, m_query);
553                                 verifyError(GL_INVALID_VALUE);
554                         }
555                 }
556
557                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
558
559                 return STOP;
560         }
561
562 protected:
563         GLuint m_query;
564 };
565
566 /*
567  API Already Active Error Test
568
569  * Check that calling BeginQuery with target TRANSFORM_FEEDBACK_OVERFLOW_ARB
570  generates an INVALID_OPERATION error if there is already an active
571  query for TRANSFORM_FEEDBACK_OVERFLOW_ARB.
572
573  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
574  BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB
575  generates an INVALID_OPERATION error if there is already an active
576  query for TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB for the specified
577  index.
578
579  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
580  BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB
581  generates an INVALID_OPERATION error if the specified query is already
582  active on another TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB target with
583  a different index.
584  */
585 class TransformFeedbackOverflowQueryErrorAlreadyActive : public TransformFeedbackOverflowQueryErrorBase
586 {
587 public:
588         TransformFeedbackOverflowQueryErrorAlreadyActive(deqp::Context&                                                   context,
589                                                                                                          TransformFeedbackOverflowQueryTests::API api, const char* name)
590                 : TransformFeedbackOverflowQueryErrorBase(context, api, name,
591                                                                                                   "Verifies whether an INVALID_OPERATION error is properly generated "
592                                                                                                   "if BeginQuery[Indexed] is used to try to start "
593                                                                                                   "a query on an index that has already a query active, or the query "
594                                                                                                   "object itself is active on another index.")
595                 , m_query(0)
596                 , m_active_overflow_query(0)
597                 , m_active_stream_overflow_query(0)
598                 , m_active_query_stream_index(0)
599         {
600         }
601
602         /* Test case init. */
603         virtual void init()
604         {
605                 TransformFeedbackOverflowQueryErrorBase::init();
606
607                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
608
609                 gl.genQueries(1, &m_query);
610
611                 gl.genQueries(1, &m_active_overflow_query);
612                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_active_overflow_query);
613
614                 if (supportsTransformFeedback3())
615                 {
616                         gl.genQueries(1, &m_active_stream_overflow_query);
617                         m_active_query_stream_index = 2;
618                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_active_query_stream_index,
619                                                                  m_active_stream_overflow_query);
620                 }
621         }
622
623         /* Test case deinit */
624         virtual void deinit()
625         {
626                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
627
628                 if (supportsTransformFeedback3())
629                 {
630                         gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_active_query_stream_index);
631                         gl.deleteQueries(1, &m_active_stream_overflow_query);
632                 }
633
634                 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB);
635                 gl.deleteQueries(1, &m_active_overflow_query);
636
637                 gl.deleteQueries(1, &m_query);
638
639                 TransformFeedbackOverflowQueryErrorBase::deinit();
640         }
641
642         /* Test case iterate function. Contains the actual test case logic. */
643         IterateResult iterate()
644         {
645                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
646
647                 startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is "
648                                   "TRANSFORM_FEEDBACK_OVERFLOW_ARB and there is already an active "
649                                   "query for TRANSFORM_FEEDBACK_ARB.");
650
651                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_query);
652                 verifyError(GL_INVALID_OPERATION);
653                 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0, m_query);
654                 verifyError(GL_INVALID_OPERATION);
655
656                 if (supportsTransformFeedback3())
657                 {
658                         startTest("BeginQueryIndexed must generate INVALID_OPERATION if <target> is "
659                                           "TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and there is already an active "
660                                           "query for TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB for the specified index.");
661
662                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_active_query_stream_index, m_query);
663                         verifyError(GL_INVALID_OPERATION);
664
665                         startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is "
666                                           "TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and the specified query is "
667                                           "already active on another TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB "
668                                           "target with a different index.");
669
670                         for (GLuint i = 0; i < getMaxVertexStreams(); ++i)
671                         {
672                                 if (i != m_active_query_stream_index)
673                                 {
674                                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i, m_active_stream_overflow_query);
675                                         verifyError(GL_INVALID_OPERATION);
676
677                                         if (i == 0)
678                                         {
679                                                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_active_stream_overflow_query);
680                                                 verifyError(GL_INVALID_OPERATION);
681                                         }
682                                 }
683                         }
684                 }
685
686                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
687
688                 return STOP;
689         }
690
691 protected:
692         GLuint m_query;
693         GLuint m_active_overflow_query;
694         GLuint m_active_stream_overflow_query;
695         GLuint m_active_query_stream_index;
696 };
697
698 /*
699  API Incompatible Target Error Test
700
701  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
702  BeginQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB
703  generates an INVALID_OPERATION error if the specified query was
704  previously used as a TRANSFORM_FEEDBACK_OVERFLOW_ARB query. Also check
705  the other way around.
706  */
707 class TransformFeedbackOverflowQueryErrorIncompatibleTarget : public TransformFeedbackOverflowQueryErrorBase
708 {
709 public:
710         TransformFeedbackOverflowQueryErrorIncompatibleTarget(deqp::Context&                                               context,
711                                                                                                                   TransformFeedbackOverflowQueryTests::API api,
712                                                                                                                   const char*                                                      name)
713                 : TransformFeedbackOverflowQueryErrorBase(context, api, name,
714                                                                                                   "Verifies whether an INVALID_OPERATION error is properly generated "
715                                                                                                   "if BeginQuery[Indexed] is called with one of "
716                                                                                                   "the newly introduced query targets but one that is different than "
717                                                                                                   "that used earlier on the same query object.")
718                 , m_overflow_query(0)
719                 , m_stream_overflow_query(0)
720                 , m_incompatible_query(0)
721         {
722         }
723
724         /* Test case init. */
725         virtual void init()
726         {
727                 TransformFeedbackOverflowQueryErrorBase::init();
728
729                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
730
731                 gl.genQueries(1, &m_incompatible_query);
732                 gl.beginQuery(GL_SAMPLES_PASSED, m_incompatible_query);
733                 gl.endQuery(GL_SAMPLES_PASSED);
734
735                 gl.genQueries(1, &m_overflow_query);
736                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_overflow_query);
737                 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB);
738
739                 if (supportsTransformFeedback3())
740                 {
741                         gl.genQueries(1, &m_stream_overflow_query);
742                         gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_stream_overflow_query);
743                         gl.endQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB);
744                 }
745         }
746
747         /* Test case deinit */
748         virtual void deinit()
749         {
750                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
751
752                 gl.deleteQueries(1, &m_incompatible_query);
753
754                 gl.deleteQueries(1, &m_overflow_query);
755
756                 if (supportsTransformFeedback3())
757                 {
758                         gl.deleteQueries(1, &m_stream_overflow_query);
759                 }
760
761                 TransformFeedbackOverflowQueryErrorBase::deinit();
762         }
763
764         /* Test case iterate function. Contains the actual test case logic. */
765         IterateResult iterate()
766         {
767                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
768
769                 startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is "
770                                   "TRANSFORM_FEEDBACK_OVERFLOW_ARB and the specified query was "
771                                   "previously used with another target.");
772
773                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_incompatible_query);
774                 verifyError(GL_INVALID_OPERATION);
775                 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0, m_incompatible_query);
776                 verifyError(GL_INVALID_OPERATION);
777
778                 if (supportsTransformFeedback3())
779                 {
780                         gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_stream_overflow_query);
781                         verifyError(GL_INVALID_OPERATION);
782                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0, m_stream_overflow_query);
783                         verifyError(GL_INVALID_OPERATION);
784
785                         startTest("BeginQuery[Indexed] must generate INVALID_OPERATION if <target> is "
786                                           "TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and the specified query "
787                                           "was previously used with another target.");
788
789                         gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_incompatible_query);
790                         verifyError(GL_INVALID_OPERATION);
791                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, 2, m_incompatible_query);
792                         verifyError(GL_INVALID_OPERATION);
793
794                         gl.beginQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_overflow_query);
795                         verifyError(GL_INVALID_OPERATION);
796                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, 2, m_overflow_query);
797                         verifyError(GL_INVALID_OPERATION);
798                 }
799
800                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
801
802                 return STOP;
803         }
804
805 protected:
806         GLuint m_overflow_query;
807         GLuint m_stream_overflow_query;
808         GLuint m_incompatible_query;
809 };
810
811 /*
812  API No Query Active Error Test
813
814  * Check that calling EndQuery with target TRANSFORM_FEEDBACK_OVERFLOW_ARB
815  generates an INVALID_OPERATION error if no query is active for
816  TRANSFORM_FEEDBACK_OVERFLOW_ARB.
817
818  * If GL 4.0 or ARB_transform_feedback3 is supported, check that calling
819  EndQueryIndexed with target TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB
820  generates an INVALID_OPERATION error if no query is active for
821  TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB for the specified index, even
822  if there is an active query for another index.
823  */
824 class TransformFeedbackOverflowQueryErrorNoActiveQuery : public TransformFeedbackOverflowQueryErrorBase
825 {
826 public:
827         TransformFeedbackOverflowQueryErrorNoActiveQuery(deqp::Context&                                                   context,
828                                                                                                          TransformFeedbackOverflowQueryTests::API api, const char* name)
829                 : TransformFeedbackOverflowQueryErrorBase(context, api, name,
830                                                                                                   "Verifies whether an INVALID_OPERATION error is properly generated "
831                                                                                                   "if EndQuery[Indexed] is called with a target "
832                                                                                                   "(and index) for which there isn't a currently active query.")
833                 , m_active_stream_overflow_query(0)
834                 , m_active_query_stream_index(0)
835         {
836         }
837
838         /* Test case init. */
839         virtual void init()
840         {
841                 TransformFeedbackOverflowQueryErrorBase::init();
842
843                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
844
845                 if (supportsTransformFeedback3())
846                 {
847                         gl.genQueries(1, &m_active_stream_overflow_query);
848                         m_active_query_stream_index = 2;
849                         gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_active_query_stream_index,
850                                                                  m_active_stream_overflow_query);
851                 }
852         }
853
854         /* Test case deinit */
855         virtual void deinit()
856         {
857                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
858
859                 if (supportsTransformFeedback3())
860                 {
861                         gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, m_active_query_stream_index);
862                         gl.deleteQueries(1, &m_active_stream_overflow_query);
863                 }
864
865                 TransformFeedbackOverflowQueryErrorBase::deinit();
866         }
867
868         /* Test case iterate function. Contains the actual test case logic. */
869         IterateResult iterate()
870         {
871                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
872
873                 startTest("EndQuery[Indexed] must generate INVALID_OPERATION if <target> is "
874                                   "TRANSFORM_FEEDBACK_OVERFLOW_ARB and there is no query active "
875                                   "for TRANSFORM_FEEDBACK_OVERFLOW_ARB.");
876
877                 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB);
878                 verifyError(GL_INVALID_OPERATION);
879                 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, 0);
880                 verifyError(GL_INVALID_OPERATION);
881
882                 if (supportsTransformFeedback3())
883                 {
884                         startTest("EndQuery[Indexed] must generate INVALID_OPERATION if <target> is "
885                                           "TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB and there is no query active "
886                                           "for TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB for the given index.");
887
888                         for (GLuint i = 0; i < getMaxVertexStreams(); ++i)
889                         {
890                                 if (i != m_active_query_stream_index)
891                                 {
892                                         gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i);
893                                         verifyError(GL_INVALID_OPERATION);
894
895                                         if (i == 0)
896                                         {
897                                                 gl.endQuery(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB);
898                                                 verifyError(GL_INVALID_OPERATION);
899                                         }
900                                 }
901                         }
902                 }
903
904                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
905
906                 return STOP;
907         }
908
909 protected:
910         GLuint m_active_stream_overflow_query;
911         GLuint m_active_query_stream_index;
912 };
913
914 /*
915  Base class of all functionality tests. Helps enforce the following requirements:
916
917  * Ensuring that QUERY_COUNTER_BITS is at least one for the TRANSFORM_FEEDBACK_OVERFLOW_ARB query
918  target before running any test that uses such a query's result.
919
920  * Ensuring that GL 4.0 or ARB_transform_feedback3 is supported and QUERY_COUNTER_BITS is at least
921  one for the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB query target before running any test that
922  uses such a query's result.
923  */
924 class TransformFeedbackOverflowQueryFunctionalBase : public TransformFeedbackOverflowQueryBaseTest
925 {
926 protected:
927         TransformFeedbackOverflowQueryFunctionalBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
928                                                                                                  const char* name, const char* description)
929                 : TransformFeedbackOverflowQueryBaseTest(context, api, name, description)
930                 , m_overflow_query(0)
931                 , m_stream_overflow_query(NULL)
932                 , m_query_buffer(0)
933                 , m_tf_buffer_count(0)
934                 , m_tf_buffer(NULL)
935                 , m_vao(0)
936                 , m_program(0)
937                 , m_checker_program(NULL)
938         {
939         }
940
941         /* Tells whether functional tests using TRANSFORM_FEEDBACK_OVERFLOW_ARB are runnable */
942         bool canTestOverflow()
943         {
944                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
945                 GLint                             counterBits;
946
947                 gl.getQueryiv(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, GL_QUERY_COUNTER_BITS, &counterBits);
948
949                 return counterBits > 0;
950         }
951
952         /* Tells whether functional tests using TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB are runnable */
953         bool canTestStreamOverflow()
954         {
955                 if (supportsTransformFeedback3())
956                 {
957                         const glw::Functions& gl = m_context.getRenderContext().getFunctions();
958                         GLint                             counterBits;
959
960                         gl.getQueryiv(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, GL_QUERY_COUNTER_BITS, &counterBits);
961
962                         return counterBits > 0;
963                 }
964                 else
965                 {
966                         return false;
967                 }
968         }
969
970         /* Dummy vertex shader. */
971         const char* dummyVsh()
972         {
973                 return "#version 150 core\n"
974                            "void main() {\n"
975                            "    gl_Position = vec4(0.0, 0.0, 0.0, 1.0);\n"
976                            "}\n";
977         }
978
979         /* Dummy fragment shader */
980         const char* dummyFsh()
981         {
982                 return "#version 150 core\n"
983                            "void main() {}\n";
984         }
985
986         /* Functional test init. Creates necessary query objects. */
987         virtual void init()
988         {
989                 TransformFeedbackOverflowQueryBaseTest::init();
990
991                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
992
993                 if (canTestOverflow())
994                 {
995                         // Setup vertex array
996                         gl.genVertexArrays(1, &m_vao);
997                         gl.bindVertexArray(m_vao);
998
999                         // Setup queries
1000                         gl.genQueries(1, &m_overflow_query);
1001
1002                         if (canTestStreamOverflow())
1003                         {
1004                                 m_stream_overflow_query = new GLuint[getMaxVertexStreams()];
1005
1006                                 gl.genQueries(getMaxVertexStreams(), m_stream_overflow_query);
1007                         }
1008
1009                         // Setup checker program
1010                         m_checker_program =
1011                                 new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources(dummyVsh(), dummyFsh()));
1012                         if (!m_checker_program->isOk())
1013                         {
1014                                 TCU_FAIL("Checker program compilation failed");
1015                         }
1016
1017                         // Setup transform feedback shader and buffers
1018                         buildTransformFeedbackProgram();
1019                         setupTransformFeedbackBuffers();
1020                 }
1021                 else
1022                 {
1023                         throw tcu::NotSupportedError(
1024                                 "QUERY_COUNTER_BITS for TRANSFORM_FEEDBACK_OVERFLOW_ARB queries is zero, skipping test");
1025                 }
1026         }
1027
1028         /* Functional test deinit. Deletes created query objects */
1029         virtual void deinit()
1030         {
1031                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1032
1033                 gl.deleteVertexArrays(1, &m_vao);
1034
1035                 gl.deleteQueries(1, &m_overflow_query);
1036
1037                 if (canTestStreamOverflow())
1038                 {
1039                         if (m_stream_overflow_query != NULL)
1040                         {
1041                                 gl.deleteQueries(getMaxVertexStreams(), m_stream_overflow_query);
1042
1043                                 delete[] m_stream_overflow_query;
1044                         }
1045                 }
1046
1047                 if (m_checker_program != NULL)
1048                 {
1049                         delete m_checker_program;
1050                 }
1051
1052                 gl.useProgram(0);
1053                 gl.deleteProgram(m_program);
1054
1055                 if (m_tf_buffer != NULL)
1056                 {
1057                         gl.deleteBuffers(m_tf_buffer_count, m_tf_buffer);
1058
1059                         delete[] m_tf_buffer;
1060                 }
1061
1062                 TransformFeedbackOverflowQueryBaseTest::deinit();
1063         }
1064
1065         /*
1066          Basic Checking Mechanism
1067
1068          * Call BeginConditionalRender with mode QUERY_WAIT and with the given
1069          query object as parameters. Draw something, then call EndConditional-
1070          Render. If the expected result for the query is FALSE, expect
1071          conditional render to discard the previous draw command.
1072
1073          * If GL 4.5 or ARB_conditional_render_inverted is supported, call Begin-
1074          ConditionalRender with mode QUERY_WAIT_INVERTED and with the given query
1075          object as parameters. Draw something, then call EndConditionalRender. If
1076          the expected result for the query is TRUE, expect conditional render to
1077          discard the previous draw command.
1078
1079          * Finally, check using GetQueryObjectiv with QUERY_RESULT that the result
1080          of the query matches the expected result.
1081
1082          * If GL 4.4 or ARB_query_buffer_object is supported then check the result
1083          of the query against the expected result also by having a query buffer
1084          bound at the time of calling GetQueryObjectiv.
1085          */
1086         bool verifyQueryResult(GLuint query, GLboolean expected)
1087         {
1088                 const glw::Functions& gl         = m_context.getRenderContext().getFunctions();
1089                 bool                              result = true;
1090                 GLuint                            actual;
1091
1092                 GLuint current_program = m_context.getContextInfo().getInt(GL_CURRENT_PROGRAM);
1093                 GLuint checker_query, check_result;
1094
1095                 // We'll use a PRIMITIVES_GENERATED query to test whether conditional
1096                 // rendering actually executed the draw command or not. If the draw command
1097                 // was discarded then the PRIMITIVES_GENERATED query should have a result
1098                 // of zero.
1099                 gl.genQueries(1, &checker_query);
1100
1101                 gl.useProgram(m_checker_program->getProgram());
1102
1103                 // Verify that conditional render discards the rendering if the expected
1104                 // result is FALSE and renders otherwise.
1105                 gl.beginConditionalRender(query, GL_QUERY_WAIT);
1106                 gl.beginQuery(GL_PRIMITIVES_GENERATED, checker_query);
1107                 gl.drawArrays(GL_POINTS, 0, 1);
1108                 gl.endQuery(GL_PRIMITIVES_GENERATED);
1109                 gl.endConditionalRender();
1110                 gl.getQueryObjectuiv(checker_query, GL_QUERY_RESULT, &check_result);
1111                 if (check_result != (GLuint)expected)
1112                 {
1113                         result = false;
1114                 }
1115
1116                 // Verify that an inverted conditional render discards the rendering if
1117                 // the expected result is TRUE and renders otherwise.
1118                 if (supportsConditionalRenderInverted())
1119                 {
1120                         gl.beginConditionalRender(query, GL_QUERY_WAIT_INVERTED);
1121                         gl.beginQuery(GL_PRIMITIVES_GENERATED, checker_query);
1122                         gl.drawArrays(GL_POINTS, 0, 1);
1123                         gl.endQuery(GL_PRIMITIVES_GENERATED);
1124                         gl.endConditionalRender();
1125                         gl.getQueryObjectuiv(checker_query, GL_QUERY_RESULT, &check_result);
1126                         if (check_result == (GLuint)expected)
1127                         {
1128                                 result = false;
1129                         }
1130                 }
1131
1132                 gl.useProgram(current_program);
1133
1134                 // Verify that the result of the query matches the expected result.
1135                 gl.getQueryObjectuiv(query, GL_QUERY_RESULT, &actual);
1136                 if ((GLboolean)actual != expected)
1137                 {
1138                         result = false;
1139                 }
1140
1141                 // Verify that the result of the query matches the expected result even
1142                 // when using a query buffer.
1143                 if (supportsQueryBufferObject())
1144                 {
1145                         const GLuint initValue = 0xDEADBEEF;
1146
1147                         gl.genBuffers(1, &m_query_buffer);
1148                         gl.bindBuffer(GL_QUERY_BUFFER, m_query_buffer);
1149                         gl.bufferData(GL_QUERY_BUFFER, sizeof(initValue), &initValue, GL_STREAM_READ);
1150                         gl.getQueryObjectuiv(query, GL_QUERY_RESULT, NULL);
1151                         gl.getBufferSubData(GL_QUERY_BUFFER, 0, sizeof(actual), &actual);
1152                         gl.deleteBuffers(1, &m_query_buffer);
1153
1154                         if ((GLboolean)actual != expected)
1155                         {
1156                                 result = false;
1157                         }
1158                 }
1159
1160                 gl.deleteQueries(1, &checker_query);
1161
1162                 return result;
1163         }
1164
1165         /* Verifies the result of all queries. There can only be up to 5 non-FALSE result queries as none of
1166          the tests use more than 4 vertex streams so the rest is assumed to always have a FALSE result. */
1167         void verifyQueryResults(GLboolean any, GLboolean stream0, GLboolean stream1, GLboolean stream2 = GL_FALSE,
1168                                                         GLboolean stream3 = GL_FALSE)
1169         {
1170                 bool result = true;
1171
1172                 // Verify the result of the TRANSFORM_FEEDBACK_OVERFLOW_ARB query.
1173                 result &= verifyQueryResult(m_overflow_query, any);
1174
1175                 if (supportsTransformFeedback3())
1176                 {
1177                         // Verify the result of the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB queries
1178                         // corresponding to the first 4 vertex streams.
1179                         result &= verifyQueryResult(m_stream_overflow_query[0], stream0);
1180                         result &= verifyQueryResult(m_stream_overflow_query[1], stream1);
1181                         result &= verifyQueryResult(m_stream_overflow_query[2], stream2);
1182                         result &= verifyQueryResult(m_stream_overflow_query[3], stream3);
1183
1184                         // Expect the rest of the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB queries
1185                         // to have a FALSE result.
1186                         for (GLuint i = 4; i < getMaxVertexStreams(); ++i)
1187                         {
1188                                 result &= verifyQueryResult(m_stream_overflow_query[i], GL_FALSE);
1189                         }
1190                 }
1191
1192                 if (!result)
1193                 {
1194                         TCU_FAIL("Failed to validate the results of the queries");
1195                 }
1196         }
1197
1198         /* Single stream version of verifyQueryResults */
1199         void verifyQueryResults(GLboolean result)
1200         {
1201                 verifyQueryResults(result, result, GL_FALSE, GL_FALSE, GL_FALSE);
1202         }
1203
1204         /* Compiles and links transform feedback program. */
1205         void buildTransformFeedbackProgram()
1206         {
1207                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1208
1209                 GLint status;
1210
1211                 m_program = gl.createProgram();
1212
1213                 const char* vsSource = transformFeedbackVertexShader();
1214
1215                 GLuint vShader = gl.createShader(GL_VERTEX_SHADER);
1216                 gl.shaderSource(vShader, 1, (const char**)&vsSource, NULL);
1217                 gl.compileShader(vShader);
1218                 gl.getShaderiv(vShader, GL_COMPILE_STATUS, &status);
1219                 if (status == GL_FALSE)
1220                 {
1221                         GLint infoLogLength = 0;
1222                         gl.getShaderiv(vShader, GL_INFO_LOG_LENGTH, &infoLogLength);
1223
1224                         std::vector<char> infoLogBuf(infoLogLength + 1);
1225                         gl.getShaderInfoLog(vShader, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]);
1226
1227                         std::string infoLog = &infoLogBuf[0];
1228                         m_testCtx.getLog().writeShader(QP_SHADER_TYPE_VERTEX, vsSource, false, infoLog.c_str());
1229
1230                         gl.deleteShader(vShader);
1231
1232                         TCU_FAIL("Failed to compile transform feedback vertex shader");
1233                 }
1234                 gl.attachShader(m_program, vShader);
1235                 gl.deleteShader(vShader);
1236
1237                 const char* gsSource = transformFeedbackGeometryShader();
1238
1239                 if (gsSource)
1240                 {
1241                         GLuint gShader = gl.createShader(GL_GEOMETRY_SHADER);
1242                         gl.shaderSource(gShader, 1, (const char**)&gsSource, NULL);
1243                         gl.compileShader(gShader);
1244                         gl.getShaderiv(gShader, GL_COMPILE_STATUS, &status);
1245                         if (status == GL_FALSE)
1246                         {
1247                                 GLint infoLogLength = 0;
1248                                 gl.getShaderiv(gShader, GL_INFO_LOG_LENGTH, &infoLogLength);
1249
1250                                 std::vector<char> infoLogBuf(infoLogLength + 1);
1251                                 gl.getShaderInfoLog(gShader, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]);
1252
1253                                 std::string infoLog = &infoLogBuf[0];
1254                                 m_testCtx.getLog().writeShader(QP_SHADER_TYPE_GEOMETRY, gsSource, false, infoLog.c_str());
1255
1256                                 gl.deleteShader(gShader);
1257
1258                                 TCU_FAIL("Failed to compile transform feedback geometry shader");
1259                         }
1260                         gl.attachShader(m_program, gShader);
1261                         gl.deleteShader(gShader);
1262                 }
1263
1264                 gl.transformFeedbackVaryings(m_program, varyingsCount(), varyings(), bufferMode());
1265                 gl.linkProgram(m_program);
1266                 gl.getProgramiv(m_program, GL_LINK_STATUS, &status);
1267                 if (status == GL_FALSE)
1268                 {
1269                         GLint infoLogLength = 0;
1270                         gl.getProgramiv(m_program, GL_INFO_LOG_LENGTH, &infoLogLength);
1271
1272                         std::vector<char> infoLogBuf(infoLogLength + 1);
1273                         gl.getProgramInfoLog(m_program, (GLsizei)infoLogBuf.size(), NULL, &infoLogBuf[0]);
1274
1275                         std::string infoLog = &infoLogBuf[0];
1276                         m_testCtx.getLog().writeShader(QP_SHADER_TYPE_VERTEX, vsSource, true, infoLog.c_str());
1277
1278                         TCU_FAIL("Failed to link transform feedback program");
1279                 }
1280
1281                 gl.useProgram(m_program);
1282         }
1283
1284         /* Generates a number of transform feedback buffers and binds them. */
1285         void setupTransformFeedbackBuffers()
1286         {
1287                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1288
1289                 m_tf_buffer_count = bufferCount();
1290
1291                 m_tf_buffer = new GLuint[m_tf_buffer_count];
1292
1293                 gl.genBuffers(m_tf_buffer_count, m_tf_buffer);
1294
1295                 for (GLint i = 0; i < m_tf_buffer_count; ++i)
1296                 {
1297                         gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, m_tf_buffer[i]);
1298                         gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, bufferSize(i), NULL, GL_DYNAMIC_COPY);
1299                 }
1300         }
1301
1302         /* Starts all overflow queries. */
1303         void beginQueries()
1304         {
1305                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1306
1307                 gl.beginQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB, m_overflow_query);
1308
1309                 if (supportsTransformFeedback3())
1310                 {
1311                         for (GLuint i = 0; i < getMaxVertexStreams(); ++i)
1312                         {
1313                                 gl.beginQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i, m_stream_overflow_query[i]);
1314                         }
1315                 }
1316         }
1317
1318         /* Stops all overflow queries. */
1319         void endQueries()
1320         {
1321                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1322
1323                 gl.endQuery(GL_TRANSFORM_FEEDBACK_OVERFLOW_ARB);
1324
1325                 if (supportsTransformFeedback3())
1326                 {
1327                         for (GLuint i = 0; i < getMaxVertexStreams(); ++i)
1328                         {
1329                                 gl.endQueryIndexed(GL_TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB, i);
1330                         }
1331                 }
1332         }
1333
1334         /* Draws a set of points to vertex stream #0 while having the overflow queries active. */
1335         void drawPoints(GLsizei count)
1336         {
1337                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1338
1339                 beginQueries();
1340                 gl.drawArrays(GL_POINTS, 0, count);
1341                 endQueries();
1342         }
1343
1344         /* Draws a set of triangles to vertex stream #0 while having the overflow queries active. */
1345         void drawTriangles(GLsizei count)
1346         {
1347                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1348
1349                 beginQueries();
1350                 gl.drawArrays(GL_TRIANGLES, 0, count * 3);
1351                 endQueries();
1352         }
1353
1354         /* Vertex shader to use for transform feedback. */
1355         virtual const char* transformFeedbackVertexShader() = 0;
1356
1357         /* Geometry shader to use for transform feedback. */
1358         virtual const char* transformFeedbackGeometryShader() = 0;
1359
1360         /* Returns the number of transform feedback varyings. */
1361         virtual GLsizei varyingsCount() = 0;
1362
1363         /* Returns the array of transform feedback varying names. */
1364         virtual const char** varyings() = 0;
1365
1366         /* Returns the transform feedback buffer mode. */
1367         virtual GLenum bufferMode() = 0;
1368
1369         /* Returns the number of transform feedback buffers. */
1370         virtual GLsizei bufferCount() = 0;
1371
1372         /* Returns the size of the specified transform feedback buffer. */
1373         virtual GLsizei bufferSize(GLint index) = 0;
1374
1375 protected:
1376         GLuint                          m_overflow_query;
1377         GLuint*                         m_stream_overflow_query;
1378         GLuint                          m_query_buffer;
1379         GLsizei                         m_tf_buffer_count;
1380         GLuint*                         m_tf_buffer;
1381         GLuint                          m_vao;
1382         GLuint                          m_program;
1383         glu::ShaderProgram* m_checker_program;
1384 };
1385
1386 /*
1387  Base class for all single stream test cases.
1388  */
1389 class TransformFeedbackOverflowQuerySingleStreamBase : public TransformFeedbackOverflowQueryFunctionalBase
1390 {
1391 protected:
1392         TransformFeedbackOverflowQuerySingleStreamBase(deqp::Context& context, TransformFeedbackOverflowQueryTests::API api,
1393                                                                                                    const char* name, const char* description)
1394                 : TransformFeedbackOverflowQueryFunctionalBase(context, api, name, description)
1395         {
1396         }
1397
1398         /* Vertex shader to use for transform feedback. */
1399         virtual const char* transformFeedbackVertexShader()
1400         {
1401                 return "#version 150 core\n"
1402                            "out float output1;\n"
1403                            "out float output2;\n"
1404                            "out float output3;\n"
1405                            "out float output4;\n"
1406                            "void main() {\n"
1407                            "    output1 = 1.0;\n"
1408                            "    output2 = 2.0;\n"
1409                            "    output3 = 3.0;\n"
1410                            "    output4 = 4.0;\n"
1411                            "}";
1412         }
1413
1414         /* No geometry shader for single stream test cases. */
1415         virtual const char* transformFeedbackGeometryShader()
1416         {
1417                 return NULL;
1418         }
1419
1420         /* There are a total of 4 varyings. */
1421         virtual GLsizei varyingsCount()
1422         {
1423                 return 4;
1424         }
1425
1426         /* The varying name list contains all outputs in order. */
1427         virtual const char** varyings()
1428         {
1429                 static const char* vars[] = { "output1", "output2", "output3", "output4" };
1430                 return vars;
1431         }
1432 };
1433
1434 /*
1435  Test case #1 - Basic single stream, interleaved attributes.
1436  */
1437 class TransformFeedbackOverflowQueryBasicSingleStreamInterleavedAttribs
1438         : public TransformFeedbackOverflowQuerySingleStreamBase
1439 {
1440 public:
1441         TransformFeedbackOverflowQueryBasicSingleStreamInterleavedAttribs(deqp::Context&                                                   context,
1442                                                                                                                                           TransformFeedbackOverflowQueryTests::API api,
1443                                                                                                                                           const char*                                                      name)
1444                 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name,
1445                                                                                                                  "Basic single stream, interleaved attributes.")
1446         {
1447         }
1448
1449         /* Use interleaved attributes. */
1450         virtual GLenum bufferMode()
1451         {
1452                 return GL_INTERLEAVED_ATTRIBS;
1453         }
1454
1455         /* A single transform feedback buffer is enough. */
1456         virtual GLsizei bufferCount()
1457         {
1458                 return 1;
1459         }
1460
1461         /* The transform feedback buffer should be able to capture exactly 10 vertices. */
1462         virtual GLsizei bufferSize(GLint index)
1463         {
1464                 (void)index;
1465                 return static_cast<GLsizei>(10 * sizeof(GLfloat) * varyingsCount());
1466         }
1467
1468         /* Test case iterate function. Contains the actual test case logic. */
1469         IterateResult iterate()
1470         {
1471                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1472
1473                 // Call BeginTransformFeedback with mode POINTS.
1474                 gl.beginTransformFeedback(GL_POINTS);
1475
1476                 // Start the query, submit draw that results in feeding back exactly 10
1477                 // points, then stop the query.
1478                 drawPoints(10);
1479
1480                 // Call EndTransformFeedback.
1481                 gl.endTransformFeedback();
1482
1483                 // Use the basic checking mechanism to validate that the result of the
1484                 // query is FALSE.
1485                 verifyQueryResults(GL_FALSE);
1486
1487                 // Repeat the above steps, but this time feed back more than 10 vertices
1488                 // and expect the result of the query to be TRUE.
1489                 gl.beginTransformFeedback(GL_POINTS);
1490                 drawPoints(11);
1491                 gl.endTransformFeedback();
1492                 verifyQueryResults(GL_TRUE);
1493
1494                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1495
1496                 return STOP;
1497         }
1498 };
1499
1500 /*
1501  Test case #2 - Basic single stream, separate attributes.
1502  */
1503 class TransformFeedbackOverflowQueryBasicSingleStreamSeparateAttribs
1504         : public TransformFeedbackOverflowQuerySingleStreamBase
1505 {
1506 public:
1507         TransformFeedbackOverflowQueryBasicSingleStreamSeparateAttribs(deqp::Context&                                                   context,
1508                                                                                                                                    TransformFeedbackOverflowQueryTests::API api,
1509                                                                                                                                    const char*                                                          name)
1510                 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name,
1511                                                                                                                  "Basic single stream, separate attributes.")
1512         {
1513         }
1514
1515         /* Use separate attributes. */
1516         virtual GLenum bufferMode()
1517         {
1518                 return GL_SEPARATE_ATTRIBS;
1519         }
1520
1521         /* We need a separate buffer for each varying. */
1522         virtual GLsizei bufferCount()
1523         {
1524                 return varyingsCount();
1525         }
1526
1527         /* One of the transform feedback buffers should be able to capture exactly 12 vertices,
1528          the others should be able to capture at least 15 vertices. */
1529         virtual GLsizei bufferSize(GLint index)
1530         {
1531                 if (index == 1)
1532                 {
1533                         return 12 * sizeof(GLfloat);
1534                 }
1535                 else
1536                 {
1537                         return 15 * sizeof(GLfloat);
1538                 }
1539         }
1540
1541         /* Test case iterate function. Contains the actual test case logic. */
1542         IterateResult iterate()
1543         {
1544                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1545
1546                 // Call BeginTransformFeedback with mode TRIANGLES.
1547                 gl.beginTransformFeedback(GL_TRIANGLES);
1548
1549                 // Start the query, submit draw that results in feeding back exactly 4
1550                 // triangles, then stop the query.
1551                 drawTriangles(4);
1552
1553                 // Call EndTransformFeedback.
1554                 gl.endTransformFeedback();
1555
1556                 // Use the basic checking mechanism to validate that the result of the
1557                 // query is FALSE.
1558                 verifyQueryResults(GL_FALSE);
1559
1560                 // Repeat the above steps, but this time feed back exactly 5 triangles
1561                 // and expect the result of the query to be TRUE.
1562                 gl.beginTransformFeedback(GL_TRIANGLES);
1563                 drawTriangles(5);
1564                 gl.endTransformFeedback();
1565                 verifyQueryResults(GL_TRUE);
1566
1567                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1568
1569                 return STOP;
1570         }
1571 };
1572
1573 /*
1574  Test case #3 - Advanced single stream, interleaved attributes.
1575  */
1576 class TransformFeedbackOverflowQueryAdvancedSingleStreamInterleavedAttribs
1577         : public TransformFeedbackOverflowQuerySingleStreamBase
1578 {
1579 public:
1580         TransformFeedbackOverflowQueryAdvancedSingleStreamInterleavedAttribs(deqp::Context& context,
1581                                                                                                                                                  TransformFeedbackOverflowQueryTests::API api,
1582                                                                                                                                                  const char*                                                      name)
1583                 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name,
1584                                                                                                                  "Advanced single stream, interleaved attributes.")
1585         {
1586         }
1587
1588         /* Use interleaved attributes. */
1589         virtual GLenum bufferMode()
1590         {
1591                 return GL_INTERLEAVED_ATTRIBS;
1592         }
1593
1594         /* A single transform feedback buffer is enough. */
1595         virtual GLsizei bufferCount()
1596         {
1597                 return 1;
1598         }
1599
1600         /* The transform feedback buffer should be able to capture exactly 10 vertices. */
1601         virtual GLsizei bufferSize(GLint index)
1602         {
1603                 (void)index;
1604                 return static_cast<GLsizei>(10 * sizeof(GLfloat) * varyingsCount());
1605         }
1606
1607         /* Test case iterate function. Contains the actual test case logic. */
1608         IterateResult iterate()
1609         {
1610                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1611
1612                 // If GL 4.0 and ARB_transform_feedback2 are not supported then skip this
1613                 // test case.
1614                 if (!supportsTransformFeedback2())
1615                 {
1616                         throw tcu::NotSupportedError("Required transform_feedback2 extension is not supported");
1617                 }
1618
1619                 // Call BeginTransformFeedback with mode POINTS.
1620                 gl.beginTransformFeedback(GL_POINTS);
1621
1622                 // Start the query, submit draw that results in feeding back exactly 8
1623                 // triangles, then stop the query.
1624                 drawPoints(8);
1625
1626                 // Call PauseTransformFeedback.
1627                 gl.pauseTransformFeedback();
1628
1629                 // Use the basic checking mechanism to validate that the result of the
1630                 // query is FALSE.
1631                 verifyQueryResults(GL_FALSE);
1632
1633                 // Start the query, submit draw that would result in feeding back more than
1634                 // 10 points if transform feedback wasn't paused, then stop the query.
1635                 drawPoints(11);
1636
1637                 // Use the basic checking mechanism to validate that the result of the
1638                 // query is FALSE.
1639                 verifyQueryResults(GL_FALSE);
1640
1641                 // Call ResumeTransformFeedback.
1642                 gl.resumeTransformFeedback();
1643
1644                 // Start the query, submit draw that results in feeding back exactly 1
1645                 // point, then stop the query.
1646                 drawPoints(1);
1647
1648                 // Call PauseTransformFeedback.
1649                 gl.pauseTransformFeedback();
1650
1651                 // Use the basic checking mechanism to validate that the result of the
1652                 // query is FALSE.
1653                 verifyQueryResults(GL_FALSE);
1654
1655                 // Call ResumeTransformFeedback.
1656                 gl.resumeTransformFeedback();
1657
1658                 // Start the query, submit draw that results in feeding back exactly 2
1659                 // point, then stop the query.
1660                 drawPoints(2);
1661
1662                 // Call EndTransformFeedback.
1663                 gl.endTransformFeedback();
1664
1665                 // Use the basic checking mechanism to validate that the result of the
1666                 // query is TRUE.
1667                 verifyQueryResults(GL_TRUE);
1668
1669                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1670
1671                 return STOP;
1672         }
1673 };
1674
1675 /*
1676  Test case #4 - Advanced single stream, separate attributes.
1677  */
1678 class TransformFeedbackOverflowQueryAdvancedSingleStreamSeparateAttribs
1679         : public TransformFeedbackOverflowQuerySingleStreamBase
1680 {
1681 public:
1682         TransformFeedbackOverflowQueryAdvancedSingleStreamSeparateAttribs(deqp::Context&                                                   context,
1683                                                                                                                                           TransformFeedbackOverflowQueryTests::API api,
1684                                                                                                                                           const char*                                                      name)
1685                 : TransformFeedbackOverflowQuerySingleStreamBase(context, api, name,
1686                                                                                                                  "Advanced single stream, separate attributes.")
1687         {
1688         }
1689
1690         /* Use separate attributes. */
1691         virtual GLenum bufferMode()
1692         {
1693                 return GL_SEPARATE_ATTRIBS;
1694         }
1695
1696         /* We need a separate buffer for each varying. */
1697         virtual GLsizei bufferCount()
1698         {
1699                 return varyingsCount();
1700         }
1701
1702         /* One of the transform feedback buffers should be able to capture exactly 12 vertices,
1703          the others should be able to capture at least 15 vertices. */
1704         virtual GLsizei bufferSize(GLint index)
1705         {
1706                 if (index == 2)
1707                 {
1708                         return 12 * sizeof(GLfloat);
1709                 }
1710                 else
1711                 {
1712                         return 15 * sizeof(GLfloat);
1713                 }
1714         }
1715
1716         /* Test case iterate function. Contains the actual test case logic. */
1717         IterateResult iterate()
1718         {
1719                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1720
1721                 // If GL 4.0 and ARB_transform_feedback2 are not supported then skip this
1722                 // test case.
1723                 if (!supportsTransformFeedback2())
1724                 {
1725                         throw tcu::NotSupportedError("Required transform_feedback2 extension is not supported");
1726                 }
1727
1728                 // Call BeginTransformFeedback with mode TRIANGLES.
1729                 gl.beginTransformFeedback(GL_TRIANGLES);
1730
1731                 // Start the query, submit draw that results in feeding back exactly 2
1732                 // triangles, then stop the query.
1733                 drawTriangles(2);
1734
1735                 // Call PauseTransformFeedback.
1736                 gl.pauseTransformFeedback();
1737
1738                 // Use the basic checking mechanism to validate that the result of the
1739                 // query is FALSE.
1740                 verifyQueryResults(GL_FALSE);
1741
1742                 // Start the query, submit draw that would result in feeding back more than
1743                 // 4 triangles if transform feedback wasn't paused, then stop the query.
1744                 drawTriangles(4);
1745
1746                 // Use the basic checking mechanism to validate that the result of the
1747                 // query is FALSE.
1748                 verifyQueryResults(GL_FALSE);
1749
1750                 // Call ResumeTransformFeedback.
1751                 gl.resumeTransformFeedback();
1752
1753                 // Start the query, submit draw that results in feeding back exactly 2
1754                 // triangles, then stop the query.
1755                 drawTriangles(2);
1756
1757                 // Call PauseTransformFeedback.
1758                 gl.pauseTransformFeedback();
1759
1760                 // Use the basic checking mechanism to validate that the result of the
1761                 // query is FALSE.
1762                 verifyQueryResults(GL_FALSE);
1763
1764                 // Call ResumeTransformFeedback.
1765                 gl.resumeTransformFeedback();
1766
1767                 // Start the query, submit draw that results in feeding back exactly 1
1768                 // triangles, then stop the query.
1769                 drawTriangles(1);
1770
1771                 // Call EndTransformFeedback.
1772                 gl.endTransformFeedback();
1773
1774                 // Use the basic checking mechanism to validate that the result of the
1775                 // query is TRUE.
1776                 verifyQueryResults(GL_TRUE);
1777
1778                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1779
1780                 return STOP;
1781         }
1782 };
1783
1784 /*
1785  Base class for all multiple stream test cases.
1786  */
1787 class TransformFeedbackOverflowQueryMultipleStreamsBase : public TransformFeedbackOverflowQueryFunctionalBase
1788 {
1789 protected:
1790         TransformFeedbackOverflowQueryMultipleStreamsBase(deqp::Context&                                                   context,
1791                                                                                                           TransformFeedbackOverflowQueryTests::API api, const char* name,
1792                                                                                                           const char* description)
1793                 : TransformFeedbackOverflowQueryFunctionalBase(context, api, name, description)
1794         {
1795         }
1796
1797         /* Vertex shader to use for transform feedback. */
1798         virtual const char* transformFeedbackVertexShader()
1799         {
1800                 return "#version 150 core\n"
1801                            "void main() {\n"
1802                            "}";
1803         }
1804
1805         /* Use interleaved attributes. */
1806         virtual GLenum bufferMode()
1807         {
1808                 return GL_INTERLEAVED_ATTRIBS;
1809         }
1810
1811         /* Always use 4 transform feedback buffers. */
1812         virtual GLsizei bufferCount()
1813         {
1814                 return 4;
1815         }
1816
1817         /* Draws a set of points to each vertex stream while having the overflow queries active. */
1818         void drawStreams(GLsizei count0, GLsizei count1 = 0, GLsizei count2 = 0, GLsizei count3 = 0)
1819         {
1820                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1821
1822                 GLint streamLoc = gl.getUniformLocation(m_program, "stream");
1823
1824                 beginQueries();
1825
1826                 gl.uniform1ui(streamLoc, 0);
1827                 gl.drawArrays(GL_POINTS, 0, count0);
1828
1829                 gl.uniform1ui(streamLoc, 1);
1830                 gl.drawArrays(GL_POINTS, 0, count1);
1831
1832                 gl.uniform1ui(streamLoc, 2);
1833                 gl.drawArrays(GL_POINTS, 0, count2);
1834
1835                 gl.uniform1ui(streamLoc, 3);
1836                 gl.drawArrays(GL_POINTS, 0, count3);
1837
1838                 endQueries();
1839         }
1840 };
1841
1842 /*
1843  Test case #5 - Advanced multiple streams, one buffer per stream.
1844  */
1845 class TransformFeedbackOverflowQueryMultipleStreamsOneBufferPerStream
1846         : public TransformFeedbackOverflowQueryMultipleStreamsBase
1847 {
1848 public:
1849         TransformFeedbackOverflowQueryMultipleStreamsOneBufferPerStream(deqp::Context&                                                   context,
1850                                                                                                                                         TransformFeedbackOverflowQueryTests::API api,
1851                                                                                                                                         const char*                                                              name)
1852                 : TransformFeedbackOverflowQueryMultipleStreamsBase(context, api, name,
1853                                                                                                                         "Advanced multiple streams, one buffer per stream.")
1854         {
1855         }
1856
1857         /* Geometry shader to use for transform feedback. */
1858         virtual const char* transformFeedbackGeometryShader()
1859         {
1860                 return "#version 150 core\n"
1861                            "#extension GL_ARB_gpu_shader5 : require\n"
1862                            "layout(points) in;\n"
1863                            "layout(points, max_vertices = 1) out;\n"
1864                            "layout(stream=0) out float output1;\n"
1865                            "layout(stream=1) out float output2;\n"
1866                            "layout(stream=2) out float output3;\n"
1867                            "layout(stream=3) out float output4;\n"
1868                            "uniform uint stream;\n"
1869                            "void main() {\n"
1870                            "    if (stream == 0) {\n"
1871                            "        output1 = 1.0;\n"
1872                            "        EmitStreamVertex(0);\n"
1873                            "        EndStreamPrimitive(0);\n"
1874                            "    }\n"
1875                            "    if (stream == 1) {\n"
1876                            "        output2 = 2.0;\n"
1877                            "        EmitStreamVertex(1);\n"
1878                            "        EndStreamPrimitive(1);\n"
1879                            "    }\n"
1880                            "    if (stream == 2) {\n"
1881                            "        output3 = 3.0;\n"
1882                            "        EmitStreamVertex(2);\n"
1883                            "        EndStreamPrimitive(2);\n"
1884                            "    }\n"
1885                            "    if (stream == 3) {\n"
1886                            "        output4 = 4.0;\n"
1887                            "        EmitStreamVertex(3);\n"
1888                            "        EndStreamPrimitive(3);\n"
1889                            "    }\n"
1890                            "}";
1891         }
1892
1893         /* Together with the separators there are a total of 7 varyings. */
1894         virtual GLsizei varyingsCount()
1895         {
1896                 return 7;
1897         }
1898
1899         /* Each output goes to different buffer. The mapping between vertex stream outputs and transform feedback buffers is non-identity. */
1900         virtual const char** varyings()
1901         {
1902                 static const char* vars[] = { "output4", "gl_NextBuffer", "output3", "gl_NextBuffer",
1903                                                                           "output2", "gl_NextBuffer", "output1" };
1904                 return vars;
1905         }
1906
1907         /* The size of the transform feedback buffers should be enough to be able to capture exactly 10 vertices for each vertex stream. */
1908         virtual GLsizei bufferSize(GLint index)
1909         {
1910                 (void)index;
1911                 return 10 * sizeof(GLfloat);
1912         }
1913
1914         /* Test case iterate function. Contains the actual test case logic. */
1915         IterateResult iterate()
1916         {
1917                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
1918
1919                 // If GL 4.0 and ARB_transform_feedback3 are not supported then skip this
1920                 // test case.
1921                 if (!supportsTransformFeedback3())
1922                 {
1923                         throw tcu::NotSupportedError("Required transform_feedback3 extension is not supported");
1924                 }
1925
1926                 // If GL 4.0 and ARB_gpu_shader5 are not supported then skip this
1927                 // test case.
1928                 if (!supportsGpuShader5())
1929                 {
1930                         throw tcu::NotSupportedError("Required gpu_shader5 extension is not supported");
1931                 }
1932
1933                 // Call BeginTransformFeedback with mode POINTS.
1934                 gl.beginTransformFeedback(GL_POINTS);
1935
1936                 // Start all queries, submit draw that results in feeding back exactly 8
1937                 // points for all four vertex streams, then stop the queries.
1938                 drawStreams(8, 8, 8, 8);
1939
1940                 // Call PauseTransformFeedback.
1941                 gl.pauseTransformFeedback();
1942
1943                 // Use the basic checking mechanism to validate that the result of the
1944                 // queries are all FALSE.
1945                 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1946
1947                 // Start the queries, submit draw that would result in feeding back more
1948                 // than 10 points for all four vertex streams if transform feedback wasn't
1949                 // paused, then stop the queries.
1950                 drawStreams(11, 11, 11, 11);
1951
1952                 // Use the basic checking mechanism to validate that the result of the
1953                 // queries are all FALSE.
1954                 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1955
1956                 // Call ResumeTransformFeedback.
1957                 gl.resumeTransformFeedback();
1958
1959                 // Start the queries, submit draw that results in feeding back exactly 3
1960                 // points only for vertex streams #1 and #3, then stop the queries.
1961                 drawStreams(0, 3, 0, 3);
1962
1963                 // Call PauseTransformFeedback.
1964                 gl.pauseTransformFeedback();
1965
1966                 // Use the basic checking mechanism to validate that the result of the
1967                 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW_ARB
1968                 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB queries for
1969                 // vertex streams #1 and #3, which should have a TRUE result.
1970                 verifyQueryResults(GL_TRUE, GL_FALSE, GL_TRUE, GL_FALSE, GL_TRUE);
1971
1972                 // Call ResumeTransformFeedback.
1973                 gl.resumeTransformFeedback();
1974
1975                 // Start the queries, submit draw that results in feeding back exactly 2
1976                 // points only for vertex streams #0 and #2, then stop the queries.
1977                 drawStreams(2, 0, 2, 0);
1978
1979                 // Call PauseTransformFeedback.
1980                 gl.pauseTransformFeedback();
1981
1982                 // Use the basic checking mechanism to validate that the result of the
1983                 // queries are all FALSE.
1984                 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1985
1986                 // Call ResumeTransformFeedback.
1987                 gl.resumeTransformFeedback();
1988
1989                 // Start the queries, submit draw that results in feeding back exactly 1
1990                 // point for vertex streams #2 and #3, then stop the queries.
1991                 drawStreams(0, 0, 1, 1);
1992
1993                 // Call EndTransformFeedback.
1994                 gl.endTransformFeedback();
1995
1996                 // Use the basic checking mechanism to validate that the result of the
1997                 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW_ARB
1998                 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB queries for
1999                 // vertex streams #2 and #3, which should have a TRUE result.
2000                 verifyQueryResults(GL_TRUE, GL_FALSE, GL_FALSE, GL_TRUE, GL_TRUE);
2001
2002                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2003
2004                 return STOP;
2005         }
2006 };
2007
2008 /*
2009  Test case #6 - Advanced multiple streams, multiple buffers per stream.
2010  */
2011 class TransformFeedbackOverflowQueryMultipleStreamsMultipleBufferPerStream
2012         : public TransformFeedbackOverflowQueryMultipleStreamsBase
2013 {
2014 public:
2015         TransformFeedbackOverflowQueryMultipleStreamsMultipleBufferPerStream(deqp::Context& context,
2016                                                                                                                                                  TransformFeedbackOverflowQueryTests::API api,
2017                                                                                                                                                  const char*                                                      name)
2018                 : TransformFeedbackOverflowQueryMultipleStreamsBase(context, api, name,
2019                                                                                                                         "Advanced multiple streams, multiple buffers per stream.")
2020         {
2021         }
2022
2023         /* Geometry shader to use for transform feedback. */
2024         virtual const char* transformFeedbackGeometryShader()
2025         {
2026                 return "#version 150 core\n"
2027                            "#extension GL_ARB_gpu_shader5 : require\n"
2028                            "layout(points) in;\n"
2029                            "layout(points, max_vertices = 1) out;\n"
2030                            "layout(stream=0) out float output1;\n"
2031                            "layout(stream=0) out float output2;\n"
2032                            "layout(stream=1) out float output3;\n"
2033                            "layout(stream=1) out float output4;\n"
2034                            "uniform uint stream;\n"
2035                            "void main() {\n"
2036                            "    if (stream == 0) {\n"
2037                            "        output1 = 1.0;\n"
2038                            "        output2 = 2.0;\n"
2039                            "        EmitStreamVertex(0);\n"
2040                            "        EndStreamPrimitive(0);\n"
2041                            "    }\n"
2042                            "    if (stream == 1) {\n"
2043                            "        output3 = 3.0;\n"
2044                            "        output4 = 4.0;\n"
2045                            "        EmitStreamVertex(1);\n"
2046                            "        EndStreamPrimitive(1);\n"
2047                            "    }\n"
2048                            "}";
2049         }
2050
2051         /* Together with the separators there are a total of 7 varyings. */
2052         virtual GLsizei varyingsCount()
2053         {
2054                 return 7;
2055         }
2056
2057         /* Vertex stream #0 is captured by transform feedback buffers #1 and #2, while
2058          vertex stream #1 is captured by transform feedback buffers #3 and #0. */
2059         virtual const char** varyings()
2060         {
2061                 static const char* vars[] = { "output4", "gl_NextBuffer", "output1", "gl_NextBuffer",
2062                                                                           "output2", "gl_NextBuffer", "output3" };
2063                 return vars;
2064         }
2065
2066         /* Transform feedback buffers #0 and #1 should be able to capture exactly 10 vertices, while
2067          transform feedback buffers #2 and #3 should be able to capture exactly 20 vertices. */
2068         virtual GLsizei bufferSize(GLint index)
2069         {
2070                 if (index < 2)
2071                 {
2072                         return 10 * sizeof(GLfloat);
2073                 }
2074                 else
2075                 {
2076                         return 20 * sizeof(GLfloat);
2077                 }
2078         }
2079
2080         /* Test case iterate function. Contains the actual test case logic. */
2081         IterateResult iterate()
2082         {
2083                 const glw::Functions& gl = m_context.getRenderContext().getFunctions();
2084
2085                 // If GL 4.0 and ARB_transform_feedback3 are not supported then skip this
2086                 // test case.
2087                 if (!supportsTransformFeedback3())
2088                 {
2089                         throw tcu::NotSupportedError("Required transform_feedback3 extension is not supported");
2090                 }
2091
2092                 // If GL 4.0 and ARB_gpu_shader5 are not supported then skip this
2093                 // test case.
2094                 if (!supportsGpuShader5())
2095                 {
2096                         throw tcu::NotSupportedError("Required gpu_shader5 extension is not supported");
2097                 }
2098
2099                 // Call BeginTransformFeedback with mode POINTS.
2100                 gl.beginTransformFeedback(GL_POINTS);
2101
2102                 // Start all queries, submit draw that results in feeding back exactly 8
2103                 // points to both vertex streams, then stop the queries.
2104                 drawStreams(8, 8);
2105
2106                 // Call PauseTransformFeedback.
2107                 gl.pauseTransformFeedback();
2108
2109                 // Use the basic checking mechanism to validate that the result of the
2110                 // queries are all FALSE.
2111                 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE);
2112
2113                 // Start the queries, submit draw that would result in feeding back more
2114                 // than 10 points for both vertex streams if transform feedback wasn't
2115                 // paused, then stop the queries.
2116                 drawStreams(11, 11);
2117
2118                 // Use the basic checking mechanism to validate that the result of the
2119                 // queries are all FALSE.
2120                 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE);
2121
2122                 // Call ResumeTransformFeedback.
2123                 gl.resumeTransformFeedback();
2124
2125                 // Start the queries, submit draw that results in feeding back exactly 1
2126                 // point for vertex stream #0 and exactly 3 points for vertex stream #1,
2127                 // then stop the queries.
2128                 drawStreams(1, 3);
2129
2130                 // Call PauseTransformFeedback.
2131                 gl.pauseTransformFeedback();
2132
2133                 // Use the basic checking mechanism to validate that the result of the
2134                 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW_ARB
2135                 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB query for vertex
2136                 // stream #1, which should have a TRUE result.
2137                 verifyQueryResults(GL_TRUE, GL_FALSE, GL_TRUE);
2138
2139                 // Call ResumeTransformFeedback.
2140                 gl.resumeTransformFeedback();
2141
2142                 // Start the queries, submit draw that results in feeding back exactly 1
2143                 // point only for vertex stream #0, then stop the queries.
2144                 drawStreams(1, 0);
2145
2146                 // Call PauseTransformFeedback.
2147                 gl.pauseTransformFeedback();
2148
2149                 // Use the basic checking mechanism to validate that the result of the
2150                 // queries are all FALSE.
2151                 verifyQueryResults(GL_FALSE, GL_FALSE, GL_FALSE);
2152
2153                 // Call ResumeTransformFeedback.
2154                 gl.resumeTransformFeedback();
2155
2156                 // Start the queries, submit draw that results in feeding back exactly 1
2157                 // point for vertex streams #0 and #1, then stop the queries.
2158                 drawStreams(1, 1);
2159
2160                 // Call EndTransformFeedback.
2161                 gl.endTransformFeedback();
2162
2163                 // Use the basic checking mechanism to validate that the result of the
2164                 // queries are all FALSE, except for the TRANSFORM_FEEDBACK_OVERFLOW_ARB
2165                 // query, and the TRANSFORM_FEEDBACK_STREAM_OVERFLOW_ARB queries for
2166                 // vertex streams #0 and #1, which should have a TRUE result.
2167                 verifyQueryResults(GL_TRUE, GL_TRUE, GL_TRUE);
2168
2169                 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2170
2171                 return STOP;
2172         }
2173 };
2174
2175 const char* apiToTestName(TransformFeedbackOverflowQueryTests::API api)
2176 {
2177         switch (api)
2178         {
2179         case TransformFeedbackOverflowQueryTests::API_GL_ARB_transform_feedback_overflow_query:
2180                 return "transform_feedback_overflow_query_ARB";
2181         }
2182         DE_ASSERT(0);
2183         return "";
2184 }
2185
2186 /** Constructor.
2187  *
2188  *  @param context Rendering context.
2189  *  @param api     API to test (core vs ARB extension)
2190  **/
2191 TransformFeedbackOverflowQueryTests::TransformFeedbackOverflowQueryTests(deqp::Context& context, API api)
2192         : TestCaseGroup(context, apiToTestName(api), "Verifies \"transform_feedback_overflow_query\" functionality")
2193         , m_api(api)
2194 {
2195         /* Left blank on purpose */
2196 }
2197
2198 /** Destructor.
2199  *
2200  **/
2201 TransformFeedbackOverflowQueryTests::~TransformFeedbackOverflowQueryTests()
2202 {
2203 }
2204
2205 /** Initializes the texture_barrier test group.
2206  *
2207  **/
2208 void TransformFeedbackOverflowQueryTests::init(void)
2209 {
2210         addChild(new TransformFeedbackOverflowQueryImplDepState(m_context, m_api, "implementation-dependent-state"));
2211         addChild(new TransformFeedbackOverflowQueryDefaultState(m_context, m_api, "default-context-state"));
2212         addChild(new TransformFeedbackOverflowQueryStateUpdate(m_context, m_api, "context-state-update"));
2213         addChild(new TransformFeedbackOverflowQueryErrorInvalidIndex(m_context, m_api, "error-invalid-index"));
2214         addChild(new TransformFeedbackOverflowQueryErrorAlreadyActive(m_context, m_api, "error-already-active"));
2215         addChild(new TransformFeedbackOverflowQueryErrorIncompatibleTarget(m_context, m_api, "error-incompatible-target"));
2216         addChild(new TransformFeedbackOverflowQueryErrorNoActiveQuery(m_context, m_api, "error-no-active-query"));
2217         addChild(new TransformFeedbackOverflowQueryBasicSingleStreamInterleavedAttribs(
2218                 m_context, m_api, "basic-single-stream-interleaved-attribs"));
2219         addChild(new TransformFeedbackOverflowQueryBasicSingleStreamSeparateAttribs(
2220                 m_context, m_api, "basic-single-stream-separate-attribs"));
2221         addChild(new TransformFeedbackOverflowQueryAdvancedSingleStreamInterleavedAttribs(
2222                 m_context, m_api, "advanced-single-stream-interleaved-attribs"));
2223         addChild(new TransformFeedbackOverflowQueryAdvancedSingleStreamSeparateAttribs(
2224                 m_context, m_api, "advanced-single-stream-separate-attribs"));
2225         addChild(new TransformFeedbackOverflowQueryMultipleStreamsOneBufferPerStream(
2226                 m_context, m_api, "multiple-streams-one-buffer-per-stream"));
2227         addChild(new TransformFeedbackOverflowQueryMultipleStreamsMultipleBufferPerStream(
2228                 m_context, m_api, "multiple-streams-multiple-buffers-per-stream"));
2229 }
2230 } /* glcts namespace */