1 /*-------------------------------------------------------------------------
2 * OpenGL Conformance Test Suite
3 * -----------------------------
4 *
5 * Copyright (c) 2015-2016 The Khronos Group Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 */ /*!
20 * \file
21 * \brief
22 */ /*-------------------------------------------------------------------*/
23
24 /**
25 */ /*!
26 * \file gl4cDirectStateAccessQueriesTests.cpp
27 * \brief Conformance tests for the Direct State Access feature functionality (Queries access part).
28 */ /*-----------------------------------------------------------------------------------------------------------*/
29
30 /* Includes. */
31 #include "gl4cDirectStateAccessTests.hpp"
32
33 #include "deSharedPtr.hpp"
34
35 #include "gluContextInfo.hpp"
36 #include "gluDefs.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluStrUtil.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 /* Define OpenGL enumerations not available in framework. */
50 #ifndef GL_QUERY_TARGET
51 #define GL_QUERY_TARGET 0x82EA
52 #endif
53
54 namespace gl4cts
55 {
56 namespace DirectStateAccess
57 {
58 namespace Queries
59 {
60 /******************************** Creation Test Implementation ********************************/
61
62 /** @brief Creation Test constructor.
63 *
64 * @param [in] context OpenGL context.
65 */
CreationTest(deqp::Context & context)66 CreationTest::CreationTest(deqp::Context &context)
67 : deqp::TestCase(context, "queries_creation", "Query Objects Creation Test")
68 {
69 /* Intentionally left blank. */
70 }
71
72 /** @brief Iterate Creation Test cases.
73 *
74 * @return Iteration result.
75 */
iterate()76 tcu::TestNode::IterateResult CreationTest::iterate()
77 {
78 /* Shortcut for GL functionality. */
79 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
80
81 /* Get context setup. */
82 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
83 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
84
85 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
86 {
87 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
88
89 return STOP;
90 }
91
92 /* Running tests. */
93 bool is_ok = true;
94 bool is_error = false;
95
96 /* Query targets */
97 static const glw::GLenum targets[] = {
98 GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, GL_TIME_ELAPSED,
99 GL_TIMESTAMP, GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
100 static const glw::GLuint targets_count = sizeof(targets) / sizeof(targets[0]);
101
102 /* Queries objects */
103 static const glw::GLuint queries_count = 2;
104
105 glw::GLuint queries_legacy[queries_count] = {};
106 glw::GLuint queries_dsa[targets_count][queries_count] = {};
107
108 try
109 {
110 /* Check legacy state creation. */
111 gl.genQueries(queries_count, queries_legacy);
112 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenQueries have failed");
113
114 for (glw::GLuint i = 0; i < queries_count; ++i)
115 {
116 if (gl.isQuery(queries_legacy[i]))
117 {
118 is_ok = false;
119
120 /* Log. */
121 m_context.getTestContext().getLog()
122 << tcu::TestLog::Message
123 << "GenQueries has created default objects, but it should create only a names."
124 << tcu::TestLog::EndMessage;
125 }
126 }
127
128 /* Check direct state creation. */
129 for (glw::GLuint i = 0; i < targets_count; ++i)
130 {
131 gl.createQueries(targets[i], queries_count, queries_dsa[i]);
132 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
133
134 for (glw::GLuint j = 0; j < queries_count; ++j)
135 {
136 if (!gl.isQuery(queries_dsa[i][j]))
137 {
138 is_ok = false;
139
140 /* Log. */
141 m_context.getTestContext().getLog()
142 << tcu::TestLog::Message << "CreateQueries has not created default objects."
143 << tcu::TestLog::EndMessage;
144 }
145 }
146 }
147 }
148 catch (...)
149 {
150 is_ok = false;
151 is_error = true;
152 }
153
154 /* Cleanup. */
155 for (glw::GLuint j = 0; j < queries_count; ++j)
156 {
157 if (queries_legacy[j])
158 {
159 gl.deleteQueries(1, &queries_legacy[j]);
160
161 queries_legacy[j] = 0;
162 }
163
164 for (glw::GLuint i = 0; i < targets_count; ++i)
165 {
166 if (queries_dsa[i][j])
167 {
168 gl.deleteQueries(1, &queries_dsa[i][j]);
169
170 queries_dsa[i][j] = 0;
171 }
172 }
173 }
174
175 /* Result's setup. */
176 if (is_ok)
177 {
178 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
179 }
180 else
181 {
182 if (is_error)
183 {
184 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
185 }
186 else
187 {
188 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
189 }
190 }
191
192 return STOP;
193 }
194
195 /******************************** Defaults Test Implementation ********************************/
196
197 /** @brief Defaults Test constructor.
198 *
199 * @param [in] context OpenGL context.
200 */
DefaultsTest(deqp::Context & context)201 DefaultsTest::DefaultsTest(deqp::Context &context)
202 : deqp::TestCase(context, "queries_defaults", "Queries Defaults Test")
203 , m_query_dsa(0)
204 {
205 /* Intentionally left blank. */
206 }
207
208 /** @brief Iterate Defaults Test cases.
209 *
210 * @return Iteration result.
211 */
iterate()212 tcu::TestNode::IterateResult DefaultsTest::iterate()
213 {
214 /* Get context setup. */
215 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
216 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
217
218 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
219 {
220 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
221
222 return STOP;
223 }
224
225 /* Running tests. */
226 bool is_ok = true;
227 bool is_error = false;
228
229 /* Query targets. */
230 static const glw::GLenum targets[] = {
231 GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, GL_TIME_ELAPSED,
232 GL_TIMESTAMP, GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
233
234 static const glw::GLchar *target_names[] = {
235 "GL_SAMPLES_PASSED", "GL_ANY_SAMPLES_PASSED", "GL_ANY_SAMPLES_PASSED_CONSERVATIVE", "GL_TIME_ELAPSED",
236 "GL_TIMESTAMP", "GL_PRIMITIVES_GENERATED", "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"};
237
238 static const glw::GLuint targets_count = sizeof(targets) / sizeof(targets[0]);
239
240 try
241 {
242 /* Check direct state creation. */
243 for (glw::GLuint i = 0; i < targets_count; ++i)
244 {
245 prepare(targets[i]);
246
247 is_ok &= testQueryParameter(GL_QUERY_RESULT, GL_FALSE, target_names[i]);
248 is_ok &= testQueryParameter(GL_QUERY_RESULT_AVAILABLE, GL_TRUE, target_names[i]);
249
250 clean();
251 }
252 }
253 catch (...)
254 {
255 is_ok = false;
256 is_error = true;
257
258 clean();
259 }
260
261 /* Result's setup. */
262 if (is_ok)
263 {
264 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
265 }
266 else
267 {
268 if (is_error)
269 {
270 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
271 }
272 else
273 {
274 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
275 }
276 }
277
278 return STOP;
279 }
280
281 /** @brief Create Query Objects.
282 *
283 * @note The function may throw if unexpected error has occured.
284 *
285 * @return True if test succeeded, false otherwise.
286 */
prepare(const glw::GLenum target)287 void DefaultsTest::prepare(const glw::GLenum target)
288 {
289 /* Shortcut for GL functionality. */
290 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
291
292 /* Query object creation */
293 gl.createQueries(target, 1, &m_query_dsa);
294 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateTransformFeedbacks have failed");
295 }
296
297 /** @brief Test Query Integer Parameter.
298 *
299 * @note The function may throw if unexpected error has occured.
300 *
301 * @param [in] pname Parameter name to be tested.
302 * @param [in] expected_value Expected value for comparison.
303 * @param [in] target_name Target name of the tested query object - for logging purposes.
304 *
305 * @return True if test succeeded, false otherwise.
306 */
testQueryParameter(const glw::GLenum pname,const glw::GLuint expected_value,const glw::GLchar * target_name)307 bool DefaultsTest::testQueryParameter(const glw::GLenum pname, const glw::GLuint expected_value,
308 const glw::GLchar *target_name)
309 {
310 /* Shortcut for GL functionality. */
311 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
312
313 /* Get data. */
314 glw::GLuint value = 0;
315
316 gl.getQueryObjectuiv(m_query_dsa, pname, &value);
317 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryObjectuiv have failed");
318
319 if (expected_value != value)
320 {
321 m_context.getTestContext().getLog()
322 << tcu::TestLog::Message << "glGetQueryObjectuiv of query object with target " << target_name
323 << " with parameter " << pname << " has returned " << value << ", however " << expected_value
324 << " was expected." << tcu::TestLog::EndMessage;
325
326 return false;
327 }
328
329 return true;
330 }
331
332 /** @brief Release GL objects.
333 */
clean()334 void DefaultsTest::clean()
335 {
336 /* Shortcut for GL functionality. */
337 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
338
339 if (m_query_dsa)
340 {
341 gl.deleteQueries(1, &m_query_dsa);
342
343 m_query_dsa = 0;
344 }
345 }
346
347 /******************************** Errors Test Implementation ********************************/
348
349 /** @brief Errors Test constructor.
350 *
351 * @param [in] context OpenGL context.
352 */
ErrorsTest(deqp::Context & context)353 ErrorsTest::ErrorsTest(deqp::Context &context)
354 : deqp::TestCase(context, "queries_errors", "Queries Errors Test")
355 , m_pGetQueryBufferObjectiv(DE_NULL)
356 , m_pGetQueryBufferObjectuiv(DE_NULL)
357 , m_pGetQueryBufferObjecti64v(DE_NULL)
358 , m_pGetQueryBufferObjectui64v(DE_NULL)
359 {
360 /* Intentionally left blank. */
361 }
362
363 /** @brief Iterate Errors Test cases.
364 *
365 * @return Iteration result.
366 */
iterate()367 tcu::TestNode::IterateResult ErrorsTest::iterate()
368 {
369 /* Shortcut for GL functionality. */
370 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
371
372 /* Get context setup. */
373 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
374 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
375
376 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
377 {
378 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
379
380 return STOP;
381 }
382
383 /* Getting function pointers. */
384 m_pGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectiv;
385 m_pGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectuiv;
386 m_pGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjecti64v;
387 m_pGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectui64v;
388
389 /* Running tests. */
390 bool is_ok = true;
391 bool is_error = false;
392
393 try
394 {
395 if ((DE_NULL == m_pGetQueryBufferObjectiv) || (DE_NULL == m_pGetQueryBufferObjectuiv) ||
396 (DE_NULL == m_pGetQueryBufferObjecti64v) || (DE_NULL == m_pGetQueryBufferObjectui64v))
397 {
398 m_context.getTestContext().getLog()
399 << tcu::TestLog::Message << "Test could not get the pointers for glGetQueryBufferObject* functions."
400 << tcu::TestLog::EndMessage;
401
402 throw 0;
403 }
404
405 is_ok &= testNegativeNumberOfObjects();
406 is_ok &= testInvalidTarget();
407 is_ok &= testInvalidQueryName();
408 is_ok &= testInvalidBufferName();
409 is_ok &= testInvalidParameterName();
410 is_ok &= testBufferOverflow();
411 is_ok &= testBufferNegativeOffset();
412 }
413 catch (...)
414 {
415 is_ok = false;
416 is_error = true;
417 }
418
419 /* Result's setup. */
420 if (is_ok)
421 {
422 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
423 }
424 else
425 {
426 if (is_error)
427 {
428 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
429 }
430 else
431 {
432 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
433 }
434 }
435
436 return STOP;
437 }
438
439 /** @brief Check that CreateQueries generates INVALID_VALUE
440 * error if number of query objects to create is
441 * negative.
442 *
443 * @return True if test succeded, false otherwise.
444 */
testNegativeNumberOfObjects()445 bool ErrorsTest::testNegativeNumberOfObjects()
446 {
447 /* Shortcut for GL functionality. */
448 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
449
450 /* Test for each target. */
451 for (glw::GLuint i = 0; i < s_targets_count; ++i)
452 {
453 glw::GLuint query = 0;
454
455 gl.createQueries(s_targets[i], -1, &query); /* Create negative number of queries. */
456
457 glw::GLenum error = gl.getError();
458
459 if (GL_INVALID_VALUE != error)
460 {
461 m_context.getTestContext().getLog()
462 << tcu::TestLog::Message << "glCreateQueries called with target " << s_target_names[i]
463 << " with negative number of objects to be created (-1) has generated error " << glu::getErrorStr(error)
464 << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
465
466 if (query)
467 {
468 gl.deleteQueries(1, &query);
469
470 while (error == gl.getError())
471 ;
472
473 m_context.getTestContext().getLog()
474 << tcu::TestLog::Message << "glCreateQueries called with target " << s_target_names[i]
475 << " with negative number of objects to be created (-1) has created at least one object."
476 << tcu::TestLog::EndMessage;
477 }
478
479 return false;
480 }
481 }
482
483 return true;
484 }
485
486 /** @brief Check that CreateQueries generates INVALID_ENUM error if target is not
487 * one of accepted values:
488 * - SAMPLES_PASSED,
489 * - ANY_SAMPLES_PASSED,
490 * - ANY_SAMPLES_PASSED_CONSERVATIVE,
491 * - TIME_ELAPSED,
492 * - TIMESTAMP,
493 * - PRIMITIVES_GENERATED or
494 * - TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN.
495 *
496 * @return True if test succeded, false otherwise.
497 */
testInvalidTarget()498 bool ErrorsTest::testInvalidTarget()
499 {
500 /* Shortcut for GL functionality. */
501 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
502
503 /* Creating invalid target. */
504 glw::GLenum invalid_target = 0;
505
506 while (isTarget(++invalid_target))
507 ;
508
509 /* Test. */
510 glw::GLuint query = 0;
511
512 gl.createQueries(invalid_target, 1, &query); /* Create negative number of queries. */
513
514 glw::GLenum error = gl.getError();
515
516 if (GL_INVALID_ENUM != error)
517 {
518 m_context.getTestContext().getLog() << tcu::TestLog::Message << "glCreateQueries called with invalid target ("
519 << invalid_target << ") has generated error " << glu::getErrorStr(error)
520 << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
521
522 if (query)
523 {
524 gl.deleteQueries(1, &query);
525
526 while (error == gl.getError())
527 ;
528
529 m_context.getTestContext().getLog()
530 << tcu::TestLog::Message << "glCreateQueries called with invalid target (" << invalid_target
531 << ") has created an object." << tcu::TestLog::EndMessage;
532 }
533
534 return false;
535 }
536
537 return true;
538 }
539
540 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
541 * GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
542 * INVALID_OPERATION error if <id> is not the name of a query object, or
543 * if the query object named by <id> is currently active.
544 *
545 * @return True if test succeded, false otherwise.
546 */
testInvalidQueryName()547 bool ErrorsTest::testInvalidQueryName()
548 {
549 /* Shortcut for GL functionality. */
550 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
551
552 /* Creating invalid query name. */
553 glw::GLuint invalid_query = 0;
554
555 /* Default result. */
556 bool is_ok = true;
557 bool is_error = false;
558
559 while (gl.isQuery(++invalid_query))
560 ;
561
562 /* Test's objects. */
563 glw::GLuint buffer = 0;
564 glw::GLuint query = 0;
565
566 try
567 {
568 /* Creating buffer for the test. */
569 gl.genBuffers(1, &buffer);
570 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
571
572 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
573 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
574
575 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
576 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
577
578 /* Test invalid query object name (integer version). */
579 m_pGetQueryBufferObjectiv(invalid_query, buffer, GL_QUERY_RESULT, 0);
580
581 glw::GLenum error = gl.getError();
582
583 if (GL_INVALID_OPERATION != error)
584 {
585 m_context.getTestContext().getLog()
586 << tcu::TestLog::Message
587 << "glGetQueryBufferObjectiv called with invalid query name has generated error "
588 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
589 << tcu::TestLog::EndMessage;
590
591 is_ok = false;
592 }
593
594 /* Test invalid query object name (unsigned integer version). */
595 m_pGetQueryBufferObjectuiv(invalid_query, buffer, GL_QUERY_RESULT, 0);
596
597 error = gl.getError();
598
599 if (GL_INVALID_OPERATION != error)
600 {
601 m_context.getTestContext().getLog()
602 << tcu::TestLog::Message
603 << "glGetQueryBufferObjectuiv called with invalid query name has generated error "
604 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
605 << tcu::TestLog::EndMessage;
606
607 is_ok = false;
608 }
609
610 /* Test invalid query object name (64-bit integer version). */
611 m_pGetQueryBufferObjecti64v(invalid_query, buffer, GL_QUERY_RESULT, 0);
612
613 error = gl.getError();
614
615 if (GL_INVALID_OPERATION != error)
616 {
617 m_context.getTestContext().getLog()
618 << tcu::TestLog::Message
619 << "glGetQueryBufferObjecti64v called with invalid query name has generated error "
620 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
621 << tcu::TestLog::EndMessage;
622
623 is_ok = false;
624 }
625
626 /* Test invalid query object name (64-bit unsigned integer version). */
627 m_pGetQueryBufferObjectui64v(invalid_query, buffer, GL_QUERY_RESULT, 0);
628
629 error = gl.getError();
630
631 if (GL_INVALID_OPERATION != error)
632 {
633 m_context.getTestContext().getLog()
634 << tcu::TestLog::Message
635 << "glGetQueryBufferObjectui64v called with invalid query name has generated error "
636 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
637 << tcu::TestLog::EndMessage;
638
639 is_ok = false;
640 }
641
642 /* Create query object for the test. */
643 gl.createQueries(s_targets[0], 1, &query);
644 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
645
646 gl.beginQuery(s_targets[0], query);
647 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
648
649 /* Test query of active query object name (integer version). */
650 m_pGetQueryBufferObjectiv(query, buffer, GL_QUERY_RESULT, 0);
651
652 error = gl.getError();
653
654 if (GL_INVALID_OPERATION != error)
655 {
656 m_context.getTestContext().getLog()
657 << tcu::TestLog::Message
658 << "glGetQueryBufferObjectiv called with active query object has generated error "
659 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
660 << tcu::TestLog::EndMessage;
661
662 is_ok = false;
663 }
664
665 /* Test query of active query object name (unsigned integer version). */
666 m_pGetQueryBufferObjectuiv(query, buffer, GL_QUERY_RESULT, 0);
667
668 error = gl.getError();
669
670 if (GL_INVALID_OPERATION != error)
671 {
672 m_context.getTestContext().getLog()
673 << tcu::TestLog::Message
674 << "glGetQueryBufferObjectuiv called with active query object has generated error "
675 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
676 << tcu::TestLog::EndMessage;
677
678 is_ok = false;
679 }
680
681 /* Test query of active query object name (64-bit integer version). */
682 m_pGetQueryBufferObjecti64v(query, buffer, GL_QUERY_RESULT, 0);
683
684 error = gl.getError();
685
686 if (GL_INVALID_OPERATION != error)
687 {
688 m_context.getTestContext().getLog()
689 << tcu::TestLog::Message
690 << "glGetQueryBufferObjecti64v called with active query object has generated error "
691 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
692 << tcu::TestLog::EndMessage;
693
694 is_ok = false;
695 }
696
697 /* Test query of active query object name (64-bit unsigned integer version). */
698 m_pGetQueryBufferObjectui64v(query, buffer, GL_QUERY_RESULT, 0);
699
700 error = gl.getError();
701
702 if (GL_INVALID_OPERATION != error)
703 {
704 m_context.getTestContext().getLog()
705 << tcu::TestLog::Message
706 << "glGetQueryBufferObjectui64v called with active query object has generated error "
707 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
708 << tcu::TestLog::EndMessage;
709
710 is_ok = false;
711 }
712 }
713 catch (...)
714 {
715 is_error = true;
716 }
717
718 /* Releasing objects. */
719 if (query)
720 {
721 gl.endQuery(s_targets[0]);
722
723 gl.deleteQueries(1, &query);
724 }
725
726 if (buffer)
727 {
728 gl.deleteBuffers(1, &buffer);
729 }
730
731 /* Error cleanup. */
732 while (gl.getError())
733 ;
734
735 if (is_error)
736 {
737 throw 0;
738 }
739
740 return is_ok;
741 }
742
743 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
744 * GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
745 * INVALID_OPERATION error if <buffer> is not the name of an existing
746 * buffer object.
747 *
748 * @return True if test succeded, false otherwise.
749 */
testInvalidBufferName()750 bool ErrorsTest::testInvalidBufferName()
751 {
752 /* Shortcut for GL functionality. */
753 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
754
755 /* Default result. */
756 bool is_ok = true;
757 bool is_error = false;
758
759 /* Creating invalid buffer name. */
760 glw::GLuint invalid_buffer = 0;
761
762 while (gl.isBuffer(++invalid_buffer))
763 ;
764
765 /* Test's objects. */
766 glw::GLuint query = 0;
767
768 try
769 {
770 /* Create query object for the test. */
771 gl.createQueries(s_targets[0], 1, &query);
772 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
773
774 /* Test query of invalid buffer name (integer version). */
775 m_pGetQueryBufferObjectiv(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
776
777 glw::GLenum error = gl.getError();
778
779 if (GL_INVALID_OPERATION != error)
780 {
781 m_context.getTestContext().getLog()
782 << tcu::TestLog::Message
783 << "glGetQueryBufferObjectiv which could generate buffers overflow generated error "
784 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
785 << tcu::TestLog::EndMessage;
786
787 is_ok = false;
788 }
789
790 /* Test query of invalid buffer name (unsigned integer version). */
791 m_pGetQueryBufferObjectuiv(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
792
793 error = gl.getError();
794
795 if (GL_INVALID_OPERATION != error)
796 {
797 m_context.getTestContext().getLog()
798 << tcu::TestLog::Message
799 << "glGetQueryBufferObjectuiv which could generate buffers overflow generated error "
800 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
801 << tcu::TestLog::EndMessage;
802
803 is_ok = false;
804 }
805
806 /* Test query of invalid buffer name (64-bit integer version). */
807 m_pGetQueryBufferObjecti64v(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
808
809 error = gl.getError();
810
811 if (GL_INVALID_OPERATION != error)
812 {
813 m_context.getTestContext().getLog()
814 << tcu::TestLog::Message
815 << "glGetQueryBufferObjecti64v which could generate buffers overflow generated error "
816 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
817 << tcu::TestLog::EndMessage;
818
819 is_ok = false;
820 }
821
822 /* Test query of invalid buffer name (64-bit unsigned integer version). */
823 m_pGetQueryBufferObjectui64v(query, invalid_buffer, GL_QUERY_RESULT_AVAILABLE, 0);
824
825 error = gl.getError();
826
827 if (GL_INVALID_OPERATION != error)
828 {
829 m_context.getTestContext().getLog()
830 << tcu::TestLog::Message
831 << "glGetQueryBufferObjectui64v which could generate buffers overflow generated error "
832 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
833 << tcu::TestLog::EndMessage;
834
835 is_ok = false;
836 }
837 }
838 catch (...)
839 {
840 is_error = true;
841 }
842
843 /* Releasing objects. */
844 if (query)
845 {
846 gl.deleteQueries(1, &query);
847 }
848
849 /* Error cleanup. */
850 while (gl.getError())
851 ;
852
853 if (is_error)
854 {
855 throw 0;
856 }
857
858 return is_ok;
859 }
860
861 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
862 * GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
863 * INVALID_ENUM error if <pname> is not QUERY_RESULT,
864 * QUERY_RESULT_AVAILABLE, QUERY_RESULT_NO_WAIT or QUERY_TARGET.
865 *
866 * @return True if test succeded, false otherwise.
867 */
testInvalidParameterName()868 bool ErrorsTest::testInvalidParameterName()
869 {
870 /* Shortcut for GL functionality. */
871 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
872
873 /* Creating invalid parameter name. */
874 glw::GLuint invalid_pname = 0;
875
876 while (isParameterName(++invalid_pname))
877 ;
878
879 /* Default result. */
880 bool is_ok = true;
881 bool is_error = false;
882
883 /* Test's objects. */
884 glw::GLuint buffer = 0;
885 glw::GLuint query = 0;
886
887 try
888 {
889 /* Creating buffer for the test. */
890 gl.genBuffers(1, &buffer);
891 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
892
893 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
894 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
895
896 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
897 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
898
899 /* Create query object for the test. */
900 gl.createQueries(s_targets[0], 1, &query);
901 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
902
903 /* Test query of invalid parameter name (integer version). */
904 m_pGetQueryBufferObjectiv(query, buffer, invalid_pname, 0);
905
906 glw::GLenum error = gl.getError();
907
908 if (GL_INVALID_ENUM != error)
909 {
910 m_context.getTestContext().getLog()
911 << tcu::TestLog::Message
912 << "glGetQueryBufferObjectiv called with invalid parameter name has generated error "
913 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
914
915 is_ok = false;
916 }
917
918 /* Test query of invalid parameter name (unsigned integer version). */
919 m_pGetQueryBufferObjectuiv(query, buffer, invalid_pname, 0);
920
921 error = gl.getError();
922
923 if (GL_INVALID_ENUM != error)
924 {
925 m_context.getTestContext().getLog()
926 << tcu::TestLog::Message
927 << "glGetQueryBufferObjectuiv called with invalid parameter name has generated error "
928 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
929
930 is_ok = false;
931 }
932
933 /* Test query of invalid parameter name (64-bit integer version). */
934 m_pGetQueryBufferObjecti64v(query, buffer, invalid_pname, 0);
935
936 error = gl.getError();
937
938 if (GL_INVALID_ENUM != error)
939 {
940 m_context.getTestContext().getLog()
941 << tcu::TestLog::Message
942 << "glGetQueryBufferObjecti64v called with invalid parameter name has generated error "
943 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
944
945 is_ok = false;
946 }
947
948 /* Test query of invalid parameter name (64-bit unsigned integer version). */
949 m_pGetQueryBufferObjectui64v(query, buffer, invalid_pname, 0);
950
951 error = gl.getError();
952
953 if (GL_INVALID_ENUM != error)
954 {
955 m_context.getTestContext().getLog()
956 << tcu::TestLog::Message
957 << "glGetQueryBufferObjectui64v called with invalid parameter name has generated error "
958 << glu::getErrorStr(error) << ", however GL_INVALID_ENUM was expected." << tcu::TestLog::EndMessage;
959
960 is_ok = false;
961 }
962 }
963 catch (...)
964 {
965 is_error = true;
966 }
967
968 /* Releasing objects. */
969 if (query)
970 {
971 gl.deleteQueries(1, &query);
972 }
973
974 if (buffer)
975 {
976 gl.deleteBuffers(1, &buffer);
977 }
978
979 /* Error cleanup. */
980 while (gl.getError())
981 ;
982
983 if (is_error)
984 {
985 throw 0;
986 }
987
988 return is_ok;
989 }
990
991 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
992 * GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
993 * INVALID_OPERATION error if the query writes to a buffer object, and the
994 * specified buffer offset would cause data to be written beyond the bounds
995 * of that buffer object.
996 *
997 * @return True if test succeded, false otherwise.
998 */
testBufferOverflow()999 bool ErrorsTest::testBufferOverflow()
1000 {
1001 /* Shortcut for GL functionality. */
1002 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1003
1004 /* Default result. */
1005 bool is_ok = true;
1006 bool is_error = false;
1007
1008 /* Test's objects. */
1009 glw::GLuint buffer = 0;
1010 glw::GLuint query = 0;
1011
1012 try
1013 {
1014 /* Creating buffer for the test. */
1015 gl.genBuffers(1, &buffer);
1016 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1017
1018 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1019 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1020
1021 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
1022 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1023
1024 /* Create query object for the test. */
1025 gl.createQueries(s_targets[0], 1, &query);
1026 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
1027
1028 /* Test query of buffer overflow (integer version). */
1029 m_pGetQueryBufferObjectiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1030
1031 glw::GLenum error = gl.getError();
1032
1033 if (GL_INVALID_OPERATION != error)
1034 {
1035 m_context.getTestContext().getLog()
1036 << tcu::TestLog::Message
1037 << "glGetQueryBufferObjectiv which could generate buffers overflow generated error "
1038 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1039 << tcu::TestLog::EndMessage;
1040
1041 is_ok = false;
1042 }
1043
1044 /* Test query of buffer overflow (unsigned integer version). */
1045 m_pGetQueryBufferObjectuiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1046
1047 error = gl.getError();
1048
1049 if (GL_INVALID_OPERATION != error)
1050 {
1051 m_context.getTestContext().getLog()
1052 << tcu::TestLog::Message
1053 << "glGetQueryBufferObjectuiv which could generate buffers overflow generated error "
1054 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1055 << tcu::TestLog::EndMessage;
1056
1057 is_ok = false;
1058 }
1059
1060 /* Test query of buffer overflow (64-bit integer version). */
1061 m_pGetQueryBufferObjecti64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1062
1063 error = gl.getError();
1064
1065 if (GL_INVALID_OPERATION != error)
1066 {
1067 m_context.getTestContext().getLog()
1068 << tcu::TestLog::Message
1069 << "glGetQueryBufferObjecti64v which could generate buffers overflow generated error "
1070 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1071 << tcu::TestLog::EndMessage;
1072
1073 is_ok = false;
1074 }
1075
1076 /* Test query of buffer overflow (64-bit unsigned integer version). */
1077 m_pGetQueryBufferObjectui64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, sizeof(glw::GLint64));
1078
1079 error = gl.getError();
1080
1081 if (GL_INVALID_OPERATION != error)
1082 {
1083 m_context.getTestContext().getLog()
1084 << tcu::TestLog::Message
1085 << "glGetQueryBufferObjectui64v which could generate buffers overflow generated error "
1086 << glu::getErrorStr(error) << ", however GL_INVALID_OPERATION was expected."
1087 << tcu::TestLog::EndMessage;
1088
1089 is_ok = false;
1090 }
1091 }
1092 catch (...)
1093 {
1094 is_error = true;
1095 }
1096
1097 /* Releasing objects. */
1098 if (query)
1099 {
1100 gl.deleteQueries(1, &query);
1101 }
1102
1103 if (buffer)
1104 {
1105 gl.deleteBuffers(1, &buffer);
1106 }
1107
1108 /* Error cleanup. */
1109 while (gl.getError())
1110 ;
1111
1112 if (is_error)
1113 {
1114 throw 0;
1115 }
1116
1117 return is_ok;
1118 }
1119
1120 /** @brief Check that GetQueryBufferObjectiv, GetQueryBufferObjectuiv,
1121 * GetQueryBufferObjecti64v and GetQueryBufferObjectui64v generate
1122 * INVALID_VALUE error if <offset> is negative.
1123 *
1124 * @return True if test succeded, false otherwise.
1125 */
testBufferNegativeOffset()1126 bool ErrorsTest::testBufferNegativeOffset()
1127 {
1128 /* Shortcut for GL functionality. */
1129 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1130
1131 /* Default result. */
1132 bool is_ok = true;
1133 bool is_error = false;
1134
1135 /* Test's objects. */
1136 glw::GLuint buffer = 0;
1137 glw::GLuint query = 0;
1138
1139 try
1140 {
1141 /* Creating buffer for the test. */
1142 gl.genBuffers(1, &buffer);
1143 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1144
1145 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, buffer);
1146 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1147
1148 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
1149 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffers have failed");
1150
1151 /* Create query object for the test. */
1152 gl.createQueries(s_targets[0], 1, &query);
1153 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateQueries have failed");
1154
1155 /* Test query with negative offset (integer version). */
1156 m_pGetQueryBufferObjectiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1157
1158 glw::GLenum error = gl.getError();
1159
1160 if (GL_INVALID_VALUE != error)
1161 {
1162 m_context.getTestContext().getLog()
1163 << tcu::TestLog::Message << "glGetQueryBufferObjectiv called with negative offset generated error "
1164 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1165
1166 is_ok = false;
1167 }
1168
1169 /* Test query with negative offset (unsigned integer version). */
1170 m_pGetQueryBufferObjectuiv(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1171
1172 error = gl.getError();
1173
1174 if (GL_INVALID_VALUE != error)
1175 {
1176 m_context.getTestContext().getLog()
1177 << tcu::TestLog::Message << "glGetQueryBufferObjectuiv called with negative offset generated error "
1178 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1179
1180 is_ok = false;
1181 }
1182
1183 /* Test query with negative offset (64-bit integer version). */
1184 m_pGetQueryBufferObjecti64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1185
1186 error = gl.getError();
1187
1188 if (GL_INVALID_VALUE != error)
1189 {
1190 m_context.getTestContext().getLog()
1191 << tcu::TestLog::Message << "glGetQueryBufferObjecti64v called with negative offset generated error "
1192 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1193
1194 is_ok = false;
1195 }
1196
1197 /* Test query with negative offset (64-bit unsigned integer version). */
1198 m_pGetQueryBufferObjectui64v(query, buffer, GL_QUERY_RESULT_AVAILABLE, -1);
1199
1200 error = gl.getError();
1201
1202 if (GL_INVALID_VALUE != error)
1203 {
1204 m_context.getTestContext().getLog()
1205 << tcu::TestLog::Message << "glGetQueryBufferObjectui64v called with negative offset generated error "
1206 << glu::getErrorStr(error) << ", however GL_INVALID_VALUE was expected." << tcu::TestLog::EndMessage;
1207
1208 is_ok = false;
1209 }
1210 }
1211 catch (...)
1212 {
1213 is_error = true;
1214 }
1215
1216 /* Releasing objects. */
1217 if (query)
1218 {
1219 gl.deleteQueries(1, &query);
1220 }
1221
1222 if (buffer)
1223 {
1224 gl.deleteBuffers(1, &buffer);
1225 }
1226
1227 /* Error cleanup. */
1228 while (gl.getError())
1229 ;
1230
1231 if (is_error)
1232 {
1233 throw 0;
1234 }
1235
1236 return is_ok;
1237 }
1238
1239 /** @brief Check if argument is one of the target names:
1240 * - SAMPLES_PASSED,
1241 * - TIME_ELAPSED,
1242 * - PRIMITIVES_GENERATED,
1243 * - TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN.
1244 *
1245 * @param [in] maybe_target Target to be checked.
1246 *
1247 * @return True if argument is one of the listed targets, false otherwise.
1248 */
isTarget(glw::GLenum maybe_target)1249 bool ErrorsTest::isTarget(glw::GLenum maybe_target)
1250 {
1251 for (glw::GLuint i = 0; i < s_targets_count; ++i)
1252 {
1253 if (maybe_target == s_targets[i])
1254 {
1255 return true;
1256 }
1257 }
1258
1259 return false;
1260 }
1261
1262 /** @brief Check if argument is one of the parameter names:
1263 * - QUERY_RESULT,
1264 * - QUERY_RESULT_AVAILABLE,
1265 * - QUERY_RESULT_NO_WAIT,
1266 * - QUERY_TARGET.
1267 *
1268 * @param [in] maybe_pname Parameter name to be checked.
1269 *
1270 * @return True if argument is one of the listed parameters, false otherwise.
1271 */
isParameterName(glw::GLenum maybe_pname)1272 bool ErrorsTest::isParameterName(glw::GLenum maybe_pname)
1273 {
1274 glw::GLenum pnames[] = {GL_QUERY_RESULT, GL_QUERY_RESULT_AVAILABLE, GL_QUERY_RESULT_NO_WAIT, GL_QUERY_TARGET};
1275 glw::GLuint pnames_count = sizeof(pnames) / sizeof(pnames[0]);
1276
1277 for (glw::GLuint i = 0; i < pnames_count; ++i)
1278 {
1279 if (maybe_pname == pnames[i])
1280 {
1281 return true;
1282 }
1283 }
1284
1285 return false;
1286 }
1287
1288 /** Targets to be tested. */
1289 const glw::GLenum ErrorsTest::s_targets[] = {
1290 GL_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED, GL_ANY_SAMPLES_PASSED_CONSERVATIVE, GL_TIME_ELAPSED,
1291 GL_TIMESTAMP, GL_PRIMITIVES_GENERATED, GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
1292
1293 /** Names of targets to be tested. */
1294 const glw::GLchar *ErrorsTest::s_target_names[] = {
1295 "GL_SAMPLES_PASSED", "GL_ANY_SAMPLES_PASSED", "GL_ANY_SAMPLES_PASSED_CONSERVATIVE", "GL_TIME_ELAPSED",
1296 "GL_TIMESTAMP", "GL_PRIMITIVES_GENERATED", "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN"};
1297
1298 /** Number of targets. */
1299 const glw::GLuint ErrorsTest::s_targets_count = sizeof(s_targets) / sizeof(s_targets[0]);
1300
1301 /******************************** Functional Test Implementation ********************************/
1302
1303 /** @brief Functional Test constructor.
1304 *
1305 * @param [in] context OpenGL context.
1306 */
FunctionalTest(deqp::Context & context)1307 FunctionalTest::FunctionalTest(deqp::Context &context)
1308 : deqp::TestCase(context, "queries_functional", "Queries Functional Test")
1309 , m_pGetQueryBufferObjectiv(DE_NULL)
1310 , m_pGetQueryBufferObjectuiv(DE_NULL)
1311 , m_pGetQueryBufferObjecti64v(DE_NULL)
1312 , m_pGetQueryBufferObjectui64v(DE_NULL)
1313 , m_fbo(0)
1314 , m_rbo(0)
1315 , m_vao(0)
1316 , m_bo_query(0)
1317 , m_bo_xfb(0)
1318 , m_qo(DE_NULL)
1319 , m_po(0)
1320 {
1321 /* Intentionally left blank. */
1322 }
1323
1324 /** @brief Do comparison (a == b).
1325 *
1326 * @tparam Type of the values to be compared.
1327 *
1328 * @param [in] a First value to be compared.
1329 * @param [in] b Second value to be compared.
1330 *
1331 * @return Result of the comparison.
1332 */
1333 template <typename T>
equal(T a,T b)1334 bool FunctionalTest::equal(T a, T b)
1335 {
1336 return (a == b);
1337 }
1338
1339 /** @brief Do comparison (a < b).
1340 *
1341 * @tparam Type of the values to be compared.
1342 *
1343 * @param [in] a First value to be compared.
1344 * @param [in] b Second value to be compared.
1345 *
1346 * @return Result of the comparison.
1347 */
1348 template <typename T>
less(T a,T b)1349 bool FunctionalTest::less(T a, T b)
1350 {
1351 return (a < b);
1352 }
1353
1354 /** @brief Template specialization of glGetQueryBufferObject* function for GLint.
1355 * This is pass through function to glGetQueryBufferObjectiv
1356 *
1357 * @param [in] id Query object identifier.
1358 * @param [in] buffer Buffer object identifier.
1359 * @param [in] pname Parameter name to be queried.
1360 * @param [in] offset Offset of the buffer to be saved at.
1361 */
1362 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1363 void FunctionalTest::GetQueryBufferObject<glw::GLint>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1364 glw::GLintptr offset)
1365 {
1366 m_pGetQueryBufferObjectiv(id, buffer, pname, offset);
1367 }
1368
1369 /** @brief Template specialization of glGetQueryBufferObject* function for GLuint.
1370 * This is pass through function to glGetQueryBufferObjectuiv
1371 *
1372 * @param [in] id Query object identifier.
1373 * @param [in] buffer Buffer object identifier.
1374 * @param [in] pname Parameter name to be queried.
1375 * @param [in] offset Offset of the buffer to be saved at.
1376 */
1377 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1378 void FunctionalTest::GetQueryBufferObject<glw::GLuint>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1379 glw::GLintptr offset)
1380 {
1381 m_pGetQueryBufferObjectuiv(id, buffer, pname, offset);
1382 }
1383
1384 /** @brief Template specialization of glGetQueryBufferObject* function for GLint64.
1385 * This is pass through function to glGetQueryBufferObjecti64v
1386 *
1387 * @param [in] id Query object identifier.
1388 * @param [in] buffer Buffer object identifier.
1389 * @param [in] pname Parameter name to be queried.
1390 * @param [in] offset Offset of the buffer to be saved at.
1391 */
1392 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1393 void FunctionalTest::GetQueryBufferObject<glw::GLint64>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1394 glw::GLintptr offset)
1395 {
1396 m_pGetQueryBufferObjecti64v(id, buffer, pname, offset);
1397 }
1398
1399 /** @brief Template specialization of glGetQueryBufferObject* function for GLuint64.
1400 * This is pass through function to glGetQueryBufferObjectui64v
1401 *
1402 * @param [in] id Query object identifier.
1403 * @param [in] buffer Buffer object identifier.
1404 * @param [in] pname Parameter name to be queried.
1405 * @param [in] offset Offset of the buffer to be saved at.
1406 */
1407 template <>
GetQueryBufferObject(glw::GLuint id,glw::GLuint buffer,glw::GLenum pname,glw::GLintptr offset)1408 void FunctionalTest::GetQueryBufferObject<glw::GLuint64>(glw::GLuint id, glw::GLuint buffer, glw::GLenum pname,
1409 glw::GLintptr offset)
1410 {
1411 m_pGetQueryBufferObjectui64v(id, buffer, pname, offset);
1412 }
1413
1414 /** @brief Function template fetches query result to buffer object using
1415 * glGetQueryBufferObject* function (selected on the basis of template parameter).
1416 * Then buffer is mapped and the result is compared with expected_value using comparison function.
1417 *
1418 * @tparam Templated type of fetched data.
1419 * It shall be one of glw::GL[u]int[64].
1420 *
1421 * @param [in] query Query object to be queried.
1422 * @param [in] pname Parameter name to be queried.
1423 * @param [in] expected_value Reference value to be compared.
1424 * @param [in] comparison Comparison function pointer.
1425 * Comparsion function shall NOT throw.
1426 *
1427 * @note The function may throw if unexpected error has occured.
1428 *
1429 * @return True if comparison succeeded, false otherwise.
1430 */
1431 template <typename T>
checkQueryBufferObject(glw::GLuint query,glw::GLenum pname,T expected_value,bool (* comparison)(T,T))1432 bool FunctionalTest::checkQueryBufferObject(glw::GLuint query, glw::GLenum pname, T expected_value,
1433 bool (*comparison)(T, T))
1434 {
1435 /* Shortcut for GL functionality. */
1436 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1437
1438 /* Default result. */
1439 bool is_ok = true;
1440
1441 /* Saving results to buffer. */
1442 GetQueryBufferObject<T>(query, m_bo_query, pname, 0);
1443 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetQueryBufferObject* have failed");
1444
1445 /* Mapping buffer to user space. */
1446 T *value = (T *)gl.mapBuffer(GL_QUERY_BUFFER, GL_READ_ONLY);
1447 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer have failed");
1448
1449 /* Doing test. */
1450 if (!comparison(expected_value, *value))
1451 {
1452 is_ok = false;
1453 }
1454
1455 /* Cleanup. */
1456 gl.unmapBuffer(GL_QUERY_BUFFER);
1457 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer have failed");
1458
1459 /* Return test result. */
1460 return is_ok;
1461 }
1462
1463 /** @brief Iterate Functional Test cases.
1464 *
1465 * @return Iteration result.
1466 */
iterate()1467 tcu::TestNode::IterateResult FunctionalTest::iterate()
1468 {
1469 /* Shortcut for GL functionality. */
1470 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1471
1472 /* Get context setup. */
1473 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
1474 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
1475
1476 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
1477 {
1478 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
1479
1480 return STOP;
1481 }
1482
1483 /* Fetching access point to GL functions. */
1484 m_pGetQueryBufferObjectiv = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectiv;
1485 m_pGetQueryBufferObjectuiv = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectuiv;
1486 m_pGetQueryBufferObjecti64v = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjecti64v;
1487 m_pGetQueryBufferObjectui64v = (PFNGLGETQUERYBUFFEROBJECT)gl.getQueryBufferObjectui64v;
1488
1489 /* Running tests. */
1490 bool is_ok = true;
1491 bool is_error = false;
1492
1493 try
1494 {
1495 if ((DE_NULL == m_pGetQueryBufferObjectiv) || (DE_NULL == m_pGetQueryBufferObjectuiv) ||
1496 (DE_NULL == m_pGetQueryBufferObjecti64v) || (DE_NULL == m_pGetQueryBufferObjectui64v))
1497 {
1498 m_context.getTestContext().getLog()
1499 << tcu::TestLog::Message << "Test could not get the pointers for glGetQueryBufferObject* functions."
1500 << tcu::TestLog::EndMessage;
1501
1502 throw 0;
1503 }
1504
1505 prepareView();
1506 prepareVertexArray();
1507 prepareBuffers();
1508 prepareQueries();
1509 prepareProgram();
1510
1511 draw();
1512
1513 /* Make sure that framebuffer and transform feedback buffer are filled with expectd data. */
1514 is_ok &= checkView();
1515 is_ok &= checkXFB();
1516
1517 /* Make comparisons for each query object. */
1518 for (glw::GLuint i = 0; i < s_targets_count; ++i)
1519 {
1520 /* Checking targets. */
1521 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1522 &FunctionalTest::equal<glw::GLint>);
1523 is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1524 &FunctionalTest::equal<glw::GLuint>);
1525 is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1526 &FunctionalTest::equal<glw::GLint64>);
1527 is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_TARGET, s_targets[i],
1528 &FunctionalTest::equal<glw::GLuint64>);
1529
1530 /* Checking result availability. */
1531 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1532 &FunctionalTest::equal<glw::GLint>);
1533 is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1534 &FunctionalTest::equal<glw::GLuint>);
1535 is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1536 &FunctionalTest::equal<glw::GLint64>);
1537 is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT_AVAILABLE, GL_TRUE,
1538 &FunctionalTest::equal<glw::GLuint64>);
1539
1540 if (GL_TIME_ELAPSED == s_targets[i])
1541 {
1542 /* Checking result. */
1543 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT, (glw::GLint)s_results[i],
1544 &FunctionalTest::less<glw::GLint>);
1545 is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint)s_results[i],
1546 &FunctionalTest::less<glw::GLuint>);
1547 is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLint64)s_results[i],
1548 &FunctionalTest::less<glw::GLint64>);
1549 is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint64)s_results[i],
1550 &FunctionalTest::less<glw::GLuint64>);
1551
1552 /* Checking result (no-wait). */
1553 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint)s_results[i],
1554 &FunctionalTest::less<glw::GLint>);
1555 is_ok &= checkQueryBufferObject<glw::GLuint>(
1556 m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint)s_results[i], &FunctionalTest::less<glw::GLuint>);
1557 is_ok &= checkQueryBufferObject<glw::GLint64>(
1558 m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint64)s_results[i], &FunctionalTest::less<glw::GLint64>);
1559 is_ok &=
1560 checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint64)s_results[i],
1561 &FunctionalTest::less<glw::GLuint64>);
1562 }
1563 else
1564 {
1565 /* Checking result. */
1566 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT, (glw::GLint)s_results[i],
1567 &FunctionalTest::equal<glw::GLint>);
1568 is_ok &= checkQueryBufferObject<glw::GLuint>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint)s_results[i],
1569 &FunctionalTest::equal<glw::GLuint>);
1570 is_ok &= checkQueryBufferObject<glw::GLint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLint64)s_results[i],
1571 &FunctionalTest::equal<glw::GLint64>);
1572 is_ok &= checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT, (glw::GLuint64)s_results[i],
1573 &FunctionalTest::equal<glw::GLuint64>);
1574
1575 /* Checking result (no-wait). */
1576 is_ok &= checkQueryBufferObject<glw::GLint>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint)s_results[i],
1577 &FunctionalTest::equal<glw::GLint>);
1578 is_ok &= checkQueryBufferObject<glw::GLuint>(
1579 m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint)s_results[i], &FunctionalTest::equal<glw::GLuint>);
1580 is_ok &= checkQueryBufferObject<glw::GLint64>(
1581 m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLint64)s_results[i], &FunctionalTest::equal<glw::GLint64>);
1582 is_ok &=
1583 checkQueryBufferObject<glw::GLuint64>(m_qo[i], GL_QUERY_RESULT_NO_WAIT, (glw::GLuint64)s_results[i],
1584 &FunctionalTest::equal<glw::GLuint64>);
1585 }
1586 }
1587 }
1588 catch (...)
1589 {
1590 is_ok = false;
1591 is_error = true;
1592 }
1593
1594 /* Clean up. */
1595 clean();
1596
1597 /* Result's setup. */
1598 if (is_ok)
1599 {
1600 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
1601 }
1602 else
1603 {
1604 if (is_error)
1605 {
1606 m_testCtx.setTestResult(QP_TEST_RESULT_INTERNAL_ERROR, "Error");
1607 }
1608 else
1609 {
1610 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1611 }
1612 }
1613
1614 return STOP;
1615 }
1616
1617 /** @brief Function prepares framebuffer with RGBA8 color attachment.
1618 * Viewport is set up. Content of the framebuffer is cleared.
1619 *
1620 * @note The function may throw if unexpected error has occured.
1621 */
prepareView()1622 void FunctionalTest::prepareView()
1623 {
1624 /* Shortcut for GL functionality. */
1625 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1626
1627 /* Prepare framebuffer. */
1628 gl.genFramebuffers(1, &m_fbo);
1629 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenFramebuffers call failed.");
1630
1631 gl.genRenderbuffers(1, &m_rbo);
1632 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenRenderbuffers call failed.");
1633
1634 gl.bindFramebuffer(GL_FRAMEBUFFER, m_fbo);
1635 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindFramebuffer call failed.");
1636
1637 gl.bindRenderbuffer(GL_RENDERBUFFER, m_rbo);
1638 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindRenderbuffer call failed.");
1639
1640 gl.renderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 1 /* x size */, 1 /* y size */);
1641 GLU_EXPECT_NO_ERROR(gl.getError(), "glRenderbufferStorage call failed.");
1642
1643 gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_rbo);
1644 GLU_EXPECT_NO_ERROR(gl.getError(), "glFramebufferRenderbuffer call failed.");
1645
1646 if (gl.checkFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
1647 {
1648 throw 0;
1649 }
1650
1651 gl.viewport(0, 0, 1, 1);
1652 GLU_EXPECT_NO_ERROR(gl.getError(), "glViewport call failed.");
1653
1654 /* Clear framebuffer's content. */
1655 gl.clearColor(0.0f, 0.0f, 0.0f, 0.0f);
1656 GLU_EXPECT_NO_ERROR(gl.getError(), "glClearColor call failed.");
1657
1658 gl.clear(GL_COLOR_BUFFER_BIT);
1659 GLU_EXPECT_NO_ERROR(gl.getError(), "glClear call failed.");
1660 }
1661
1662 /** @brief Function creates and binds empty vertex array.
1663 *
1664 * @note The function may throw if unexpected error has occured.
1665 */
prepareVertexArray()1666 void FunctionalTest::prepareVertexArray()
1667 {
1668 /* Shortcut for GL functionality. */
1669 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1670
1671 /* Creating and binding VAO. */
1672 gl.genVertexArrays(1, &m_vao);
1673 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenVertexArrays have failed");
1674
1675 gl.bindVertexArray(m_vao);
1676 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindVertexArray have failed");
1677 }
1678
1679 /** @brief Function creates buffers for query and transform feedback data storage.
1680 * The storage is allocated and buffers are bound to QUERY_BUFFER and
1681 * TRANSFORM_FEEDBACK_BUFFER binding points respectively.
1682 *
1683 * @note The function may throw if unexpected error has occured.
1684 */
prepareBuffers()1685 void FunctionalTest::prepareBuffers()
1686 {
1687 /* Shortcut for GL functionality. */
1688 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1689
1690 /* Buffer for storing query's result. */
1691 gl.genBuffers(1, &m_bo_query);
1692 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1693
1694 gl.bindBuffer(GL_QUERY_BUFFER, m_bo_query);
1695 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1696
1697 gl.bufferData(GL_QUERY_BUFFER, sizeof(glw::GLint64), DE_NULL, GL_DYNAMIC_COPY);
1698 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
1699
1700 /* Buffer for storing transform feedback results. */
1701 gl.genBuffers(1, &m_bo_xfb);
1702 GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers have failed");
1703
1704 gl.bindBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, m_bo_xfb);
1705 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer have failed");
1706
1707 gl.bufferData(GL_TRANSFORM_FEEDBACK_BUFFER,
1708 3 /* number of vertices per triangle */ * 2 /* number of triangles */ * sizeof(glw::GLint), DE_NULL,
1709 GL_DYNAMIC_COPY);
1710 GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData have failed");
1711
1712 gl.bindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, 0, m_bo_xfb);
1713 GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBufferBase have failed");
1714 }
1715
1716 /** @brief Function creates array of query objects using DSA-style method.
1717 *
1718 * @note The function may throw if unexpected error has occured.
1719 */
prepareQueries()1720 void FunctionalTest::prepareQueries()
1721 {
1722 /* Shortcut for GL functionality. */
1723 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1724
1725 /* Allocating memory for queries array. */
1726 m_qo = new glw::GLuint[s_targets_count];
1727
1728 if (DE_NULL == m_qo)
1729 {
1730 throw 0;
1731 }
1732
1733 /* Creating query object for each target. */
1734 for (glw::GLuint i = 0; i < s_targets_count; ++i)
1735 {
1736 gl.createQueries(s_targets[i], 1, &m_qo[i]);
1737
1738 /* Error checking. */
1739 if (GL_NO_ERROR != gl.getError())
1740 {
1741 /* Remove previous. */
1742 if (i > 0)
1743 {
1744 gl.deleteQueries(i, m_qo);
1745 }
1746
1747 /* Deallocate storage. */
1748 delete[] m_qo;
1749
1750 m_qo = DE_NULL;
1751
1752 /* Signalise test failure. */
1753 throw 0;
1754 }
1755 }
1756 }
1757
1758 /** @brief Function builds test's GLSL program.
1759 * If succeded, the program will be set to be used.
1760 *
1761 * @note The function may throw if unexpected error has occured.
1762 */
prepareProgram()1763 void FunctionalTest::prepareProgram()
1764 {
1765 /* Shortcut for GL functionality */
1766 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1767
1768 struct Shader
1769 {
1770 glw::GLchar const *const source;
1771 glw::GLenum const type;
1772 glw::GLuint id;
1773 } shader[] = {{s_vertex_shader, GL_VERTEX_SHADER, 0}, {s_fragment_shader, GL_FRAGMENT_SHADER, 0}};
1774
1775 glw::GLuint const shader_count = sizeof(shader) / sizeof(shader[0]);
1776
1777 try
1778 {
1779 /* Create program. */
1780 m_po = gl.createProgram();
1781 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateProgram call failed.");
1782
1783 /* Shader compilation. */
1784
1785 for (glw::GLuint i = 0; i < shader_count; ++i)
1786 {
1787 if (DE_NULL != shader[i].source)
1788 {
1789 shader[i].id = gl.createShader(shader[i].type);
1790
1791 GLU_EXPECT_NO_ERROR(gl.getError(), "glCreateShader call failed.");
1792
1793 gl.attachShader(m_po, shader[i].id);
1794
1795 GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader call failed.");
1796
1797 gl.shaderSource(shader[i].id, 1, &(shader[i].source), NULL);
1798
1799 GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource call failed.");
1800
1801 gl.compileShader(shader[i].id);
1802
1803 GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader call failed.");
1804
1805 glw::GLint status = GL_FALSE;
1806
1807 gl.getShaderiv(shader[i].id, GL_COMPILE_STATUS, &status);
1808 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1809
1810 if (GL_FALSE == status)
1811 {
1812 glw::GLint log_size = 0;
1813 gl.getShaderiv(shader[i].id, GL_INFO_LOG_LENGTH, &log_size);
1814 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv call failed.");
1815
1816 glw::GLchar *log_text = new glw::GLchar[log_size];
1817
1818 gl.getShaderInfoLog(shader[i].id, log_size, NULL, &log_text[0]);
1819
1820 m_context.getTestContext().getLog()
1821 << tcu::TestLog::Message << "Shader compilation has failed.\n"
1822 << "Shader type: " << glu::getShaderTypeStr(shader[i].type) << "\n"
1823 << "Shader compilation error log:\n"
1824 << log_text << "\n"
1825 << "Shader source code:\n"
1826 << shader[i].source << "\n"
1827 << tcu::TestLog::EndMessage;
1828
1829 delete[] log_text;
1830
1831 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog call failed.");
1832
1833 throw 0;
1834 }
1835 }
1836 }
1837
1838 /* Transform Feedback setup. */
1839 gl.transformFeedbackVaryings(m_po, 1, &s_xfb_varying_name, GL_INTERLEAVED_ATTRIBS);
1840 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1841
1842 /* Link. */
1843 gl.linkProgram(m_po);
1844
1845 GLU_EXPECT_NO_ERROR(gl.getError(), "glTransformFeedbackVaryings call failed.");
1846
1847 glw::GLint status = GL_FALSE;
1848
1849 gl.getProgramiv(m_po, GL_LINK_STATUS, &status);
1850
1851 if (GL_TRUE == status)
1852 {
1853 for (glw::GLuint i = 0; i < shader_count; ++i)
1854 {
1855 if (shader[i].id)
1856 {
1857 gl.detachShader(m_po, shader[i].id);
1858
1859 GLU_EXPECT_NO_ERROR(gl.getError(), "glDetachShader call failed.");
1860 }
1861 }
1862 }
1863 else
1864 {
1865 glw::GLint log_size = 0;
1866
1867 gl.getProgramiv(m_po, GL_INFO_LOG_LENGTH, &log_size);
1868
1869 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv call failed.");
1870
1871 glw::GLchar *log_text = new glw::GLchar[log_size];
1872
1873 gl.getProgramInfoLog(m_po, log_size, NULL, &log_text[0]);
1874
1875 m_context.getTestContext().getLog() << tcu::TestLog::Message << "Program linkage has failed due to:\n"
1876 << log_text << "\n"
1877 << tcu::TestLog::EndMessage;
1878
1879 delete[] log_text;
1880
1881 GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog call failed.");
1882
1883 throw 0;
1884 }
1885 }
1886 catch (...)
1887 {
1888 if (m_po)
1889 {
1890 gl.deleteProgram(m_po);
1891
1892 m_po = 0;
1893 }
1894 }
1895
1896 for (glw::GLuint i = 0; i < shader_count; ++i)
1897 {
1898 if (0 != shader[i].id)
1899 {
1900 gl.deleteShader(shader[i].id);
1901
1902 shader[i].id = 0;
1903 }
1904 }
1905
1906 if (m_po)
1907 {
1908 gl.useProgram(m_po);
1909 GLU_EXPECT_NO_ERROR(gl.getError(), "glUseProgram call failed.");
1910 }
1911
1912 if (0 == m_po)
1913 {
1914 throw 0;
1915 }
1916 }
1917
1918 /** @brief Function draws full screen quad. Queries are measured during the process.
1919 * Also, transform feedback data is captured.
1920 *
1921 * @note The function may throw if unexpected error has occured.
1922 */
draw()1923 void FunctionalTest::draw()
1924 {
1925 /* Shortcut for GL functionality. */
1926 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1927
1928 /* Start queries. */
1929 for (glw::GLuint i = 0; i < s_targets_count; ++i)
1930 {
1931 gl.beginQuery(s_targets[i], m_qo[i]);
1932 }
1933
1934 /* Start XFB. */
1935 gl.beginTransformFeedback(GL_TRIANGLES);
1936
1937 /* Draw full screen quad. */
1938 gl.drawArrays(GL_TRIANGLE_STRIP, 0, 4);
1939
1940 /* Finish XFB. */
1941 gl.endTransformFeedback();
1942
1943 /* Finish queries. */
1944 for (glw::GLuint i = 0; i < s_targets_count; ++i)
1945 {
1946 gl.endQuery(s_targets[i]);
1947 }
1948
1949 /* Make sure OpenGL finished drawing. */
1950 gl.finish();
1951
1952 /* Error checking. */
1953 GLU_EXPECT_NO_ERROR(gl.getError(), "Drawing function have failed.");
1954 }
1955
1956 /** @brief Check that framebuffer is filled with red color.
1957 */
checkView()1958 bool FunctionalTest::checkView()
1959 {
1960 /* Shortcut for GL functionality. */
1961 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1962
1963 /* Fetch framebuffer data. */
1964 glw::GLubyte pixel[4] = {0};
1965
1966 gl.readPixels(0, 0, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixel);
1967 GLU_EXPECT_NO_ERROR(gl.getError(), "glReadPixels have failed");
1968
1969 /* Comparison with expected values. */
1970 if ((255 != pixel[0]) || (0 != pixel[1]) || (0 != pixel[2]) || (255 != pixel[3]))
1971 {
1972 m_context.getTestContext().getLog()
1973 << tcu::TestLog::Message << "Frameuffer content (" << (unsigned int)pixel[0] << ", "
1974 << (unsigned int)pixel[1] << ", " << (unsigned int)pixel[2] << ", " << (unsigned int)pixel[3]
1975 << ") is different than expected (255, 0, 0, 255)." << tcu::TestLog::EndMessage;
1976
1977 return false;
1978 }
1979
1980 return true;
1981 }
1982
1983 /** @brief Check that transform feedback buffer
1984 * contains values representing quad.
1985 */
checkXFB()1986 bool FunctionalTest::checkXFB()
1987 {
1988 /* Shortcut for GL functionality */
1989 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1990
1991 /* Default result. */
1992 bool is_ok = true;
1993
1994 /* Mapping buffer object to the user-space. */
1995 glw::GLint *buffer = (glw::GLint *)gl.mapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER, GL_READ_ONLY);
1996 GLU_EXPECT_NO_ERROR(gl.getError(), "glMapBuffer call failed.");
1997
1998 if ((0 != buffer[0]) || (1 != buffer[1]) || (2 != buffer[2]) ||
1999
2000 (2 != buffer[3]) || (1 != buffer[4]) || (3 != buffer[5]))
2001 {
2002 is_ok = false;
2003 }
2004
2005 gl.unmapBuffer(GL_TRANSFORM_FEEDBACK_BUFFER);
2006 GLU_EXPECT_NO_ERROR(gl.getError(), "glUnmapBuffer call failed.");
2007
2008 return is_ok;
2009 }
2010
2011 /** @brief Release all created objects.
2012 */
clean()2013 void FunctionalTest::clean()
2014 {
2015 /* Shortcut for GL functionality. */
2016 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2017
2018 /* Releasing queries. */
2019 if (DE_NULL != m_qo)
2020 {
2021 gl.deleteQueries(s_targets_count, m_qo);
2022
2023 delete[] m_qo;
2024
2025 m_qo = DE_NULL;
2026 }
2027
2028 /* Release framebuffer. */
2029 if (m_fbo)
2030 {
2031 gl.deleteFramebuffers(1, &m_fbo);
2032
2033 m_fbo = 0;
2034 }
2035
2036 /* Release renderbuffer. */
2037 if (m_rbo)
2038 {
2039 gl.deleteRenderbuffers(1, &m_rbo);
2040
2041 m_rbo = 0;
2042 }
2043
2044 /* Release vertex array object. */
2045 if (m_vao)
2046 {
2047 gl.deleteVertexArrays(1, &m_vao);
2048
2049 m_vao = 0;
2050 }
2051
2052 /* Release buffer object for storing queries' results. */
2053 if (m_bo_query)
2054 {
2055 gl.deleteBuffers(1, &m_bo_query);
2056
2057 m_bo_query = 0;
2058 }
2059
2060 /* Release transform feedback buffer. */
2061 if (m_bo_xfb)
2062 {
2063 gl.deleteBuffers(1, &m_bo_xfb);
2064
2065 m_bo_xfb = 0;
2066 }
2067
2068 /* Release GLSL program. */
2069 if (m_po)
2070 {
2071 gl.useProgram(0);
2072
2073 gl.deleteProgram(m_po);
2074
2075 m_po = 0;
2076 }
2077 }
2078
2079 /** Targets to be tested. */
2080 const glw::GLenum FunctionalTest::s_targets[] = {GL_SAMPLES_PASSED, GL_TIME_ELAPSED, GL_PRIMITIVES_GENERATED,
2081 GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN};
2082
2083 /** Expected result for each target. */
2084 const glw::GLint FunctionalTest::s_results[] = {1, 0, 2, 2};
2085
2086 /** Number of targets. */
2087 const glw::GLuint FunctionalTest::s_targets_count = sizeof(s_targets) / sizeof(s_targets[0]);
2088
2089 /** Vertex shader source code. */
2090 const glw::GLchar FunctionalTest::s_vertex_shader[] = "#version 450\n"
2091 "\n"
2092 "out int xfb_result;\n"
2093 "\n"
2094 "void main()\n"
2095 "{\n"
2096 " switch(gl_VertexID)\n"
2097 " {\n"
2098 " case 0:\n"
2099 " gl_Position = vec4(-1.0, 1.0, 0.0, 1.0);\n"
2100 " break;\n"
2101 " case 1:\n"
2102 " gl_Position = vec4( 1.0, 1.0, 0.0, 1.0);\n"
2103 " break;\n"
2104 " case 2:\n"
2105 " gl_Position = vec4(-1.0,-1.0, 0.0, 1.0);\n"
2106 " break;\n"
2107 " case 3:\n"
2108 " gl_Position = vec4( 1.0,-1.0, 0.0, 1.0);\n"
2109 " break;\n"
2110 " }\n"
2111 "\n"
2112 " xfb_result = gl_VertexID;\n"
2113 "}\n";
2114
2115 /** Fragment shader source program. */
2116 const glw::GLchar FunctionalTest::s_fragment_shader[] = "#version 450\n"
2117 "\n"
2118 "out vec4 color;\n"
2119 "\n"
2120 "void main()\n"
2121 "{\n"
2122 " color = vec4(1.0, 0.0, 0.0, 1.0);\n"
2123 "}\n";
2124
2125 /** Name of transform feedback varying in vertex shader. */
2126 const glw::GLchar *FunctionalTest::s_xfb_varying_name = "xfb_result";
2127
2128 /******************************** Reuse Test Implementation ********************************/
2129
2130 /** @brief Reuse Test constructor.
2131 *
2132 * @param [in] context OpenGL context.
2133 */
ReuseTest(deqp::Context & context)2134 ReuseTest::ReuseTest(deqp::Context &context) : deqp::TestCase(context, "queries_reuse", "Query Objects Reuse Test")
2135 {
2136 /* Intentionally left blank. */
2137 }
2138
2139 /** @brief Iterate Reuse Test cases.
2140 *
2141 * @return Iteration result.
2142 */
iterate()2143 tcu::TestNode::IterateResult ReuseTest::iterate()
2144 {
2145 /* Shortcut for GL functionality. */
2146 const glw::Functions &gl = m_context.getRenderContext().getFunctions();
2147
2148 /* Get context setup. */
2149 bool is_at_least_gl_45 = (glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::core(4, 5)));
2150 bool is_arb_direct_state_access = m_context.getContextInfo().isExtensionSupported("GL_ARB_direct_state_access");
2151
2152 if ((!is_at_least_gl_45) && (!is_arb_direct_state_access))
2153 {
2154 m_testCtx.setTestResult(QP_TEST_RESULT_NOT_SUPPORTED, "Not Supported");
2155
2156 return STOP;
2157 }
2158
2159 /* Running tests. */
2160 bool is_ok = true;
2161
2162 GLuint query_id_a = 0;
2163 GLuint query_id_b = 0;
2164 /* Allocate query object */
2165 gl.genQueries(1, &query_id_a);
2166 /* Associate object with GL_TIMESTAMP */
2167 gl.queryCounter(query_id_a, GL_TIMESTAMP);
2168 /* Deallocate query object */
2169 gl.deleteQueries(1, &query_id_a);
2170
2171 /* Allocate query object again - should result in the same id */
2172 gl.genQueries(1, &query_id_b);
2173 /* Use the id with something else */
2174 gl.beginQuery(GL_TIME_ELAPSED, query_id_b);
2175 if (gl.getError() != 0) /* Crash was reported here. */
2176 is_ok = false;
2177 gl.endQuery(GL_TIME_ELAPSED);
2178 /* Clean up */
2179 gl.deleteQueries(1, &query_id_b);
2180
2181 if (query_id_a != query_id_b)
2182 {
2183 m_context.getTestContext().getLog()
2184 << tcu::TestLog::Message << "Note: Queries got different id:s, so no actual reuse occurred."
2185 << tcu::TestLog::EndMessage;
2186 }
2187
2188 /* Result's setup. */
2189 if (is_ok)
2190 {
2191 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
2192 }
2193 else
2194 {
2195 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
2196 }
2197
2198 return STOP;
2199 }
2200
2201 } // namespace Queries
2202 } // namespace DirectStateAccess
2203 } // namespace gl4cts
2204