Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qopengltimerquery.cpp
Go to the documentation of this file.
1// Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
6
8#include <QtCore/private/qobject_p.h>
9#include <QtGui/QOpenGLContext>
10#include <QtGui/QOpenGLFunctions>
11
12QT_BEGIN_NAMESPACE
13
14// Helper class used as fallback if OpenGL <3.3 is being used with EXT_timer_query
15class QExtTimerQueryHelper
16{
17public:
18 QExtTimerQueryHelper(QOpenGLContext *context)
19 {
20 Q_ASSERT(context);
21 GetQueryObjectui64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLuint64EXT *)>(context->getProcAddress("glGetQueryObjectui64vEXT"));
22 GetQueryObjecti64vEXT = reinterpret_cast<void (QOPENGLF_APIENTRYP)(GLuint , GLenum , GLint64EXT *)>(context->getProcAddress("glGetQueryObjecti64vEXT"));
23 }
24
25 inline void glGetQueryObjectui64vEXT(GLuint id, GLenum pname, GLuint64EXT *params)
26 {
27 GetQueryObjectui64vEXT(id, pname, params);
28 }
29
30 inline void glGetQueryObjecti64vEXT(GLuint id, GLenum pname, GLint64EXT *params)
31 {
32 GetQueryObjecti64vEXT(id, pname, params);
33 }
34
35private:
36 void (QOPENGLF_APIENTRYP GetQueryObjectui64vEXT)(GLuint id, GLenum pname, GLuint64EXT *params);
37 void (QOPENGLF_APIENTRYP GetQueryObjecti64vEXT)(GLuint id, GLenum pname, GLint64EXT *params);
38};
39
41{
42public:
45 context(nullptr),
46 ext(nullptr),
47 timeInterval(0),
48 timer(0)
49 {
50 }
51
53 {
54 delete core;
55 delete ext;
56 }
57
58 bool create();
59 void destroy();
60 void begin();
61 void end();
64 bool isResultAvailable() const;
66
67 // There are several cases we must handle:
68 // OpenGL >=3.3 includes timer queries as a core feature
69 // ARB_timer_query has same functionality as above. Requires OpenGL 3.2
70 // EXT_timer_query offers limited support. Can be used with OpenGL >=1.5
71 //
72 // Note that some implementations (OS X) provide OpenGL 3.2 but do not expose the
73 // ARB_timer_query extension. In such situations we must also be able to handle
74 // using the EXT_timer_query extension with any version of OpenGL.
75 //
76 // OpenGL 1.5 or above contains the generic query API and OpenGL 3.3 and
77 // ARB_timer_query provide the 64-bit query API. These are wrapped by
78 // QOpenGLQueryHelper. All we need to handle in addition is the EXT_timer_query
79 // case and to take care not to call the Core/ARB functions when we only
80 // have EXT_timer_query available.
83 QExtTimerQueryHelper *ext;
86};
87
89{
90 QOpenGLContext *ctx = QOpenGLContext::currentContext();
91
92 if (timer && context == ctx)
93 return true;
94
95 context = ctx;
96 if (!context) {
97 qWarning("A current OpenGL context is required to create timer query objects");
98 return false;
99 }
100
101 if (context->isOpenGLES()) {
102 qWarning("QOpenGLTimerQuery: Not supported on OpenGL ES");
103 return false;
104 }
105
106 // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query
107 core = new QOpenGLQueryHelper(context);
108
109 // Check to see if we also need to resolve the functions for EXT_timer_query
110 QSurfaceFormat f = context->format();
111 if (f.version() <= std::pair(3, 2)
112 && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
113 && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
114 ext = new QExtTimerQueryHelper(context);
115 } else if (f.version() <= std::pair(3, 2)
116 && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
117 && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
118 qWarning("QOpenGLTimerQuery requires one of:\n"
119 " OpenGL 3.3 or newer,\n"
120 " OpenGL 3.2 and the ARB_timer_query extension\n"
121 " or the EXT_timer query extension");
122 return false;
123 }
124
125 core->glGenQueries(1, &timer);
126 return (timer != 0);
127}
128
130{
131 if (!timer)
132 return;
133
134 core->glDeleteQueries(1, &timer);
135 timer = 0;
136 context = nullptr;
137}
138
139// GL_TIME_ELAPSED_EXT is not defined on OS X 10.6
140#if !defined(GL_TIME_ELAPSED_EXT)
141#define GL_TIME_ELAPSED_EXT 0x88BF
142#endif
143
144// GL_TIME_ELAPSED is not defined on OS X 10.7 or 10.8 yet
145#if !defined(GL_TIME_ELAPSED)
146#define GL_TIME_ELAPSED GL_TIME_ELAPSED_EXT
147#endif
148
150{
151 core->glBeginQuery(GL_TIME_ELAPSED, timer);
152}
153
155{
156 core->glEndQuery(GL_TIME_ELAPSED);
157}
158
160{
161 // Don't call glQueryCounter if we only have EXT_timer_query
162#if defined(GL_TIMESTAMP)
163 if (!ext)
164 core->glQueryCounter(timer, GL_TIMESTAMP);
165 else
166 qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
167#else
168 qWarning("QOpenGLTimerQuery::recordTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
169#endif
170}
171
173{
174 GLint64 tmp = 0;
175#if defined(GL_TIMESTAMP)
176 if (!ext)
177 core->glGetInteger64v(GL_TIMESTAMP, &tmp);
178 else
179 qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
180#else
181 qWarning("QOpenGLTimerQuery::waitForTimestamp() requires OpenGL 3.3 or GL_ARB_timer_query");
182#endif
183 GLuint64 timestamp(tmp);
184 return timestamp;
185}
186
188{
189 GLuint available = GL_FALSE;
190 core->glGetQueryObjectuiv(timer, GL_QUERY_RESULT_AVAILABLE, &available);
191 return available;
192}
193
195{
196 if (!ext)
197 core->glGetQueryObjectui64v(timer, GL_QUERY_RESULT, &timeInterval);
198 else
199 ext->glGetQueryObjectui64vEXT(timer, GL_QUERY_RESULT, &timeInterval);
200 return timeInterval;
201}
202
203/*!
204 \class QOpenGLTimerQuery
205 \brief The QOpenGLTimerQuery class wraps an OpenGL timer query object.
206 \inmodule QtOpenGL
207 \since 5.1
208 \ingroup painting-3D
209
210 OpenGL timer query objects are OpenGL managed resources to measure the
211 execution times of sequences of OpenGL commands on the GPU.
212
213 OpenGL offers various levels of support for timer queries, depending on
214 the version of OpenGL you have and the presence of the ARB_timer_query or
215 EXT_timer_query extensions. The support can be summarized as:
216
217 \list
218 \li OpenGL >=3.3 offers full support for all timer query functionality.
219 \li OpenGL 3.2 with the ARB_timer_query extension offers full support
220 for all timer query functionality.
221 \li OpenGL <=3.2 with the EXT_timer_query extension offers limited support
222 in that the timestamp of the GPU cannot be queried. Places where this
223 impacts functions provided by Qt classes will be highlighted in the
224 function documentation.
225 \li OpenGL ES 2 (and OpenGL ES 3) do not provide any support for OpenGL
226 timer queries.
227 \endlist
228
229 OpenGL represents time with a granularity of 1 nanosecond (1e-9 seconds). As a
230 consequence of this, 32-bit integers would only give a total possible duration
231 of approximately 4 seconds, which would not be difficult to exceed in poorly
232 performing or lengthy operations. OpenGL therefore uses 64 bit integer types
233 to represent times. A GLuint64 variable has enough width to contain a duration
234 of hundreds of years, which is plenty for real-time rendering needs.
235
236 As with the other Qt OpenGL classes, QOpenGLTimerQuery has a create()
237 function to create the underlying OpenGL object. This is to allow the developer to
238 ensure that there is a valid current OpenGL context at the time.
239
240 Once created, timer queries can be issued in one of several ways. The simplest
241 method is to delimit a block of commands with calls to begin() and end(). This
242 instructs OpenGL to measure the time taken from completing all commands issued
243 prior to begin() until the completion of all commands issued prior to end().
244
245 At the end of a frame we can retrieve the results by calling waitForResult().
246 As this function's name implies, it blocks CPU execution until OpenGL notifies
247 that the timer query result is available. To avoid blocking, you can check
248 if the query result is available by calling isResultAvailable(). Note that
249 modern GPUs are deeply pipelined and query results may not become available for
250 between 1-5 frames after they were issued.
251
252 Note that OpenGL does not permit nesting or interleaving of multiple timer queries
253 using begin() and end(). Using multiple timer queries and recordTimestamp() avoids
254 this limitation. When using recordTimestamp() the result can be obtained at
255 some later time using isResultAvailable() and waitForResult(). Qt provides the
256 convenience class QOpenGLTimeMonitor that helps with using multiple query objects.
257
258 \sa QOpenGLTimeMonitor
259*/
260
261/*!
262 Creates a QOpenGLTimerQuery instance with the given \a parent. You must call create()
263 with a valid OpenGL context before using.
264*/
265QOpenGLTimerQuery::QOpenGLTimerQuery(QObject *parent)
266 : QObject(*new QOpenGLTimerQueryPrivate, parent)
267{
268}
269
270/*!
271 Destroys the QOpenGLTimerQuery and the underlying OpenGL resource.
272*/
273QOpenGLTimerQuery::~QOpenGLTimerQuery()
274{
275 QOpenGLContext* ctx = QOpenGLContext::currentContext();
276
277 Q_D(QOpenGLTimerQuery);
278 QOpenGLContext *oldContext = nullptr;
279 if (d->context != ctx) {
280 oldContext = ctx;
281 if (d->context->makeCurrent(oldContext->surface())) {
282 ctx = d->context;
283 } else {
284 qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to make query objects's context current");
285 ctx = nullptr;
286 }
287 }
288
289 if (ctx)
290 destroy();
291
292 if (oldContext) {
293 if (!oldContext->makeCurrent(oldContext->surface()))
294 qWarning("QOpenGLTimerQuery::~QOpenGLTimerQuery() failed to restore current context");
295 }
296}
297
298/*!
299 Creates the underlying OpenGL timer query object. There must be a valid OpenGL context
300 that supports query objects current for this function to succeed.
301
302 Returns \c true if the OpenGL timer query object was successfully created.
303*/
304bool QOpenGLTimerQuery::create()
305{
306 Q_D(QOpenGLTimerQuery);
307 return d->create();
308}
309
310/*!
311 Destroys the underlying OpenGL timer query object. The context that was current when
312 create() was called must be current when calling this function.
313*/
314void QOpenGLTimerQuery::destroy()
315{
316 Q_D(QOpenGLTimerQuery);
317 d->destroy();
318}
319
320/*!
321 Returns \c true if the underlying OpenGL query object has been created. If this
322 returns \c true and the associated OpenGL context is current, then you are able to issue
323 queries with this object.
324*/
325bool QOpenGLTimerQuery::isCreated() const
326{
327 Q_D(const QOpenGLTimerQuery);
328 return (d->timer != 0);
329}
330
331/*!
332 Returns the id of the underlying OpenGL query object.
333*/
334GLuint QOpenGLTimerQuery::objectId() const
335{
336 Q_D(const QOpenGLTimerQuery);
337 return d->timer;
338}
339
340/*!
341 Marks the start point in the OpenGL command queue for a sequence of commands to
342 be timed by this query object.
343
344 This is useful for simple use-cases. Usually it is better to use recordTimestamp().
345
346 \sa end(), isResultAvailable(), waitForResult(), recordTimestamp()
347*/
348void QOpenGLTimerQuery::begin()
349{
350 Q_D(QOpenGLTimerQuery);
351 d->begin();
352}
353
354/*!
355 Marks the end point in the OpenGL command queue for a sequence of commands to
356 be timed by this query object.
357
358 This is useful for simple use-cases. Usually it is better to use recordTimestamp().
359
360 \sa begin(), isResultAvailable(), waitForResult(), recordTimestamp()
361*/
362void QOpenGLTimerQuery::end()
363{
364 Q_D(QOpenGLTimerQuery);
365 d->end();
366}
367
368/*!
369 Places a marker in the OpenGL command queue for the GPU to record the timestamp
370 when this marker is reached by the GPU. This function is non-blocking and the
371 result will become available at some later time.
372
373 The availability of the result can be checked with isResultAvailable(). The result
374 can be fetched with waitForResult() which will block if the result is not yet
375 available.
376
377 \sa waitForResult(), isResultAvailable(), begin(), end()
378*/
379void QOpenGLTimerQuery::recordTimestamp()
380{
381 Q_D(QOpenGLTimerQuery);
382 return d->recordTimestamp();
383}
384
385/*!
386 Returns the current timestamp of the GPU when all previously issued OpenGL
387 commands have been received but not necessarily executed by the GPU.
388
389 This function blocks until the result is returned.
390
391 \sa recordTimestamp()
392*/
393GLuint64 QOpenGLTimerQuery::waitForTimestamp() const
394{
395 Q_D(const QOpenGLTimerQuery);
396 return d->waitForTimeStamp();
397}
398
399/*!
400 Returns \c true if the OpenGL timer query result is available.
401
402 This function is non-blocking and ideally should be used to check for the
403 availability of the query result before calling waitForResult().
404
405 \sa waitForResult()
406*/
407bool QOpenGLTimerQuery::isResultAvailable() const
408{
409 Q_D(const QOpenGLTimerQuery);
410 return d->isResultAvailable();
411}
412
413/*!
414 Returns the result of the OpenGL timer query.
415
416 This function will block until the result is made available by OpenGL. It is
417 recommended to call isResultAvailable() to ensure that the result is available
418 to avoid unnecessary blocking and stalling.
419
420 \sa isResultAvailable()
421*/
422GLuint64 QOpenGLTimerQuery::waitForResult() const
423{
424 Q_D(const QOpenGLTimerQuery);
425 return d->result();
426}
427
428
430{
431public:
433 : QObjectPrivate(),
434 timers(),
435 timeSamples(),
436 context(nullptr),
437 core(nullptr),
438 ext(nullptr),
440 currentSample(-1),
441 timerQueryActive(false)
442 {
443 }
444
446 {
447 delete core;
448 delete ext;
449 }
450
451 bool create();
452 void destroy();
454 bool isResultAvailable() const;
457 void reset();
458
461
464 QExtTimerQueryHelper *ext;
465
468 mutable bool timerQueryActive;
469};
470
472{
473 if (!timers.isEmpty() && timers.at(0) != 0 && timers.size() == requestedSampleCount)
474 return true;
475
476 QOpenGLContext *ctx = QOpenGLContext::currentContext();
477 if (context && context != ctx) {
478 qWarning("QTimeMonitor: Attempting to use different OpenGL context to recreate timers.\n"
479 "Please call destroy() first or use the same context to previously create");
480 return false;
481 }
482
483 context = ctx;
484 if (!context) {
485 qWarning("A current OpenGL context is required to create timer query objects");
486 return false;
487 }
488
489 // Resize the vectors that hold the timers and the recorded samples
490 timers.resize(requestedSampleCount);
491 timeSamples.resize(requestedSampleCount);
492
493 // Resolve the functions provided by OpenGL 1.5 and OpenGL 3.3 or ARB_timer_query
494 core = new QOpenGLQueryHelper(context);
495
496 // Check to see if we also need to resolve the functions for EXT_timer_query
497 QSurfaceFormat f = context->format();
498 if (f.version() <= std::pair(3, 2)
499 && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
500 && context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
501 ext = new QExtTimerQueryHelper(context);
502 } else if (f.version() <= std::pair(3, 2)
503 && !context->hasExtension(QByteArrayLiteral("GL_ARB_timer_query"))
504 && !context->hasExtension(QByteArrayLiteral("GL_EXT_timer_query"))) {
505 qWarning("QOpenGLTimeMonitor requires one of:\n"
506 " OpenGL 3.3 or newer,\n"
507 " OpenGL 3.2 and the ARB_timer_query extension\n"
508 " or the EXT_timer query extension");
509 return false;
510 }
511
512 core->glGenQueries(requestedSampleCount, timers.data());
513 return (timers.at(0) != 0);
514}
515
517{
518 if (timers.isEmpty() || timers.at(0) == 0)
519 return;
520
521 core->glDeleteQueries(timers.size(), timers.data());
522 timers.clear();
523 delete core;
524 core = nullptr;
525 delete ext;
526 ext = nullptr;
527 context = nullptr;
528}
529
531{
532 // Use glQueryCounter() and GL_TIMESTAMP where available.
533 // Otherwise, simulate it with glBeginQuery()/glEndQuery()
534 if (!ext) {
535#if defined(GL_TIMESTAMP)
536 core->glQueryCounter(timers.at(++currentSample), GL_TIMESTAMP);
537#endif
538 } else {
539 if (currentSample == -1) {
540 core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample));
541 timerQueryActive = true;
542 } else if (currentSample < timers.size() - 1) {
543 core->glEndQuery(GL_TIME_ELAPSED_EXT);
544 core->glBeginQuery(GL_TIME_ELAPSED_EXT, timers.at(++currentSample));
545 } else {
546 if (timerQueryActive) {
547 core->glEndQuery(GL_TIME_ELAPSED_EXT);
548 timerQueryActive = false;
549 }
550 }
551 }
552}
553
555{
556 // The OpenGL spec says that if a query result is ready then the results of all queries
557 // of the same type issued before it must also be ready. Therefore we only need to check
558 // the availability of the result for the last issued query
559 GLuint available = GL_FALSE;
560 core->glGetQueryObjectuiv(timers.at(currentSample), GL_QUERY_RESULT_AVAILABLE, &available);
561 return available;
562}
563
565{
566 // For the Core and ARB options just ask for the timestamp for each timer query.
567 // For the EXT implementation we cannot obtain timestamps so we defer any result
568 // collection to the intervals() function
569 if (!ext) {
570 for (int i = 0; i <= currentSample; ++i)
571 core->glGetQueryObjectui64v(timers.at(i), GL_QUERY_RESULT, &timeSamples[i]);
572 } else {
573 qWarning("QOpenGLTimeMonitor::samples() requires OpenGL >=3.3\n"
574 "or OpenGL 3.2 and GL_ARB_timer_query");
575 }
576 return timeSamples;
577}
578
580{
581 QList<GLuint64> intervals(timers.size() - 1);
582 if (!ext) {
583 // Obtain the timestamp samples and calculate the interval durations
584 const QList<GLuint64> timeStamps = samples();
585 for (int i = 0; i < intervals.size(); ++i)
586 intervals[i] = timeStamps[i+1] - timeStamps[i];
587 } else {
588 // Stop the last timer if needed
589 if (timerQueryActive) {
590 core->glEndQuery(GL_TIME_ELAPSED_EXT);
591 timerQueryActive = false;
592 }
593
594 // Obtain the results from all timers apart from the redundant last one. In this
595 // case the results actually are the intervals not timestamps
596 for (int i = 0; i < currentSample; ++i)
597 ext->glGetQueryObjectui64vEXT(timers.at(i), GL_QUERY_RESULT, &intervals[i]);
598 }
599
600 return intervals;
601}
602
604{
605 currentSample = -1;
606 timeSamples.fill(0);
607}
608
609
610/*!
611 \class QOpenGLTimeMonitor
612 \brief The QOpenGLTimeMonitor class wraps a sequence of OpenGL timer query objects.
613 \inmodule QtOpenGL
614 \since 5.1
615 \ingroup painting-3D
616
617 The QOpenGLTimeMonitor class is a convenience wrapper around a collection of OpenGL
618 timer query objects used to measure intervals of time on the GPU to the level of
619 granularity required by your rendering application.
620
621 The OpenGL timer queries objects are queried in sequence to record the GPU
622 timestamps at positions of interest in your rendering code. Once the results for
623 all issues timer queries become available, the results can be fetched and
624 QOpenGLTimerMonitor will calculate the recorded time intervals for you.
625
626 The typical use case of this class is to either profile your application's rendering
627 algorithms or to adjust those algorithms in real-time for dynamic performance/quality
628 balancing.
629
630 Prior to using QOpenGLTimeMonitor in your rendering function you should set the
631 required number of sample points that you wish to record by calling setSamples(). Note
632 that measuring N sample points will produce N-1 time intervals. Once you have set the
633 number of sample points, call the create() function with a valid current OpenGL context
634 to create the necessary query timer objects. These steps are usually performed just
635 once in an initialization function.
636
637 Use the recordSample() function to delimit blocks of code containing OpenGL commands
638 that you wish to time. You can check availability of the resulting time
639 samples and time intervals with isResultAvailable(). The calculated time intervals and
640 the raw timestamp samples can be retrieved with the blocking waitForIntervals() and
641 waitForSamples() functions respectively.
642
643 After retrieving the results and before starting a new round of taking samples
644 (for example, in the next frame) be sure to call the reset() function which will clear
645 the cached results and reset the timer index back to the first timer object.
646
647 \sa QOpenGLTimerQuery
648*/
649
650/*!
651 Creates a QOpenGLTimeMonitor instance with the given \a parent. You must call create()
652 with a valid OpenGL context before using.
653
654 \sa setSampleCount(), create()
655*/
656QOpenGLTimeMonitor::QOpenGLTimeMonitor(QObject *parent)
657 : QObject(*new QOpenGLTimeMonitorPrivate, parent)
658{
659}
660
661/*!
662 Destroys the QOpenGLTimeMonitor and any underlying OpenGL resources.
663*/
664QOpenGLTimeMonitor::~QOpenGLTimeMonitor()
665{
666 QOpenGLContext* ctx = QOpenGLContext::currentContext();
667
668 Q_D(QOpenGLTimeMonitor);
669 QOpenGLContext *oldContext = nullptr;
670 if (d->context != ctx) {
671 oldContext = ctx;
672 if (d->context->makeCurrent(oldContext->surface())) {
673 ctx = d->context;
674 } else {
675 qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to make time monitor's context current");
676 ctx = nullptr;
677 }
678 }
679
680 if (ctx)
681 destroy();
682
683 if (oldContext) {
684 if (!oldContext->makeCurrent(oldContext->surface()))
685 qWarning("QOpenGLTimeMonitor::~QOpenGLTimeMonitor() failed to restore current context");
686 }
687}
688
689/*!
690 Sets the number of sample points to \a sampleCount. After setting the number
691 of samples with this function, you must call create() to instantiate the underlying
692 OpenGL timer query objects.
693
694 The new \a sampleCount must be at least 2.
695
696 \sa sampleCount(), create(), recordSample()
697*/
698void QOpenGLTimeMonitor::setSampleCount(int sampleCount)
699{
700 // We need at least 2 samples to get an interval
701 if (sampleCount < 2)
702 return;
703 Q_D(QOpenGLTimeMonitor);
704 d->requestedSampleCount = sampleCount;
705}
706
707/*!
708 Returns the number of sample points that have been requested with
709 setSampleCount(). If create was successfully called following setSampleCount(),
710 then the value returned will be the actual number of sample points
711 that can be used.
712
713 The default value for sample count is 2, leading to the measurement of a
714 single interval.
715
716 \sa setSampleCount()
717*/
718int QOpenGLTimeMonitor::sampleCount() const
719{
720 Q_D(const QOpenGLTimeMonitor);
721 return d->requestedSampleCount;
722}
723
724/*!
725 Instantiate sampleCount() OpenGL timer query objects that will be used
726 to track the amount of time taken to execute OpenGL commands between
727 successive calls to recordSample().
728
729 Returns \c true if the OpenGL timer query objects could be created.
730
731 \sa destroy(), setSampleCount(), recordSample()
732*/
733bool QOpenGLTimeMonitor::create()
734{
735 Q_D(QOpenGLTimeMonitor);
736 return d->create();
737}
738
739/*!
740 Destroys any OpenGL timer query objects used within this instance.
741
742 \sa create()
743*/
744void QOpenGLTimeMonitor::destroy()
745{
746 Q_D(QOpenGLTimeMonitor);
747 d->destroy();
748}
749
750/*!
751 Returns \c true if the underlying OpenGL query objects have been created. If this
752 returns \c true and the associated OpenGL context is current, then you are able to record
753 time samples with this object.
754*/
755bool QOpenGLTimeMonitor::isCreated() const
756{
757 Q_D(const QOpenGLTimeMonitor);
758 return (!d->timers.isEmpty() && d->timers.at(0) != 0);
759}
760
761/*!
762 Returns a QList containing the object Ids of the OpenGL timer query objects.
763*/
764QList<GLuint> QOpenGLTimeMonitor::objectIds() const
765{
766 Q_D(const QOpenGLTimeMonitor);
767 return d->timers;
768}
769
770/*!
771 Issues an OpenGL timer query at this point in the OpenGL command queue. Calling this
772 function in a sequence in your application's rendering function, will build up
773 details of the GPU time taken to execute the OpenGL commands between successive
774 calls to this function.
775
776 \sa setSampleCount(), isResultAvailable(), waitForSamples(), waitForIntervals()
777*/
778int QOpenGLTimeMonitor::recordSample()
779{
780 Q_D(QOpenGLTimeMonitor);
781 d->recordSample();
782 return d->currentSample;
783}
784
785/*!
786 Returns \c true if the OpenGL timer query results are available.
787
788 \sa waitForSamples(), waitForIntervals()
789*/
790bool QOpenGLTimeMonitor::isResultAvailable() const
791{
792 Q_D(const QOpenGLTimeMonitor);
793 return d->isResultAvailable();
794}
795
796/*!
797 Returns a QList containing the GPU timestamps taken with recordSample().
798
799 This function will block until OpenGL indicates the results are available. It
800 is recommended to check the availability of the result prior to calling this
801 function with isResultAvailable().
802
803 \note This function only works on systems that have OpenGL >=3.3 or the
804 ARB_timer_query extension. See QOpenGLTimerQuery for more details.
805
806 \sa waitForIntervals(), isResultAvailable()
807*/
808QList<GLuint64> QOpenGLTimeMonitor::waitForSamples() const
809{
810 Q_D(const QOpenGLTimeMonitor);
811 return d->samples();
812}
813
814/*!
815 Returns a QList containing the time intervals delimited by the calls to
816 recordSample(). The resulting vector will contain one fewer element as
817 this represents the intervening intervals rather than the actual timestamp
818 samples.
819
820 This function will block until OpenGL indicates the results are available. It
821 is recommended to check the availability of the result prior to calling this
822 function with isResultAvailable().
823
824 \sa waitForSamples(), isResultAvailable()
825*/
826QList<GLuint64> QOpenGLTimeMonitor::waitForIntervals() const
827{
828 Q_D(const QOpenGLTimeMonitor);
829 return d->intervals();
830}
831
832/*!
833 Resets the time monitor ready for use in another frame of rendering. Call
834 this once you have obtained the previous results and before calling
835 recordSample() for the first time on the next frame.
836
837 \sa recordSample()
838*/
839void QOpenGLTimeMonitor::reset()
840{
841 Q_D(QOpenGLTimeMonitor);
842 d->reset();
843}
844
845QT_END_NAMESPACE
846
847#include "moc_qopengltimerquery.cpp"
QList< GLuint64 > intervals() const
QExtTimerQueryHelper * ext
QList< GLuint64 > samples() const
QOpenGLQueryHelper * core
QExtTimerQueryHelper * ext
#define GL_TIME_ELAPSED_EXT
#define GL_TIME_ELAPSED