1//************************************ bs::framework - Copyright 2018 Marko Pintera **************************************//
2//*********** Licensed under the MIT license. See LICENSE.md for full terms. This notice is not to be removed. ***********//
3#include "BsGLTimerQuery.h"
4#include "BsGLCommandBuffer.h"
5#include "Math/BsMath.h"
6#include "Profiling/BsRenderStats.h"
7
8namespace bs { namespace ct
9{
10 GLTimerQuery::GLTimerQuery(UINT32 deviceIdx)
11 {
12 assert(deviceIdx == 0 && "Multiple GPUs not supported natively on OpenGL.");
13
14 GLuint queries[2];
15 glGenQueries(2, queries);
16 BS_CHECK_GL_ERROR();
17
18 mQueryStartObj = queries[0];
19 mQueryEndObj = queries[1];
20
21 BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query);
22 }
23
24 GLTimerQuery::~GLTimerQuery()
25 {
26 GLuint queries[2];
27 queries[0] = mQueryStartObj;
28 queries[1] = mQueryEndObj;
29
30 glDeleteQueries(2, queries);
31 BS_CHECK_GL_ERROR();
32
33 BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Query);
34 }
35
36 void GLTimerQuery::begin(const SPtr<CommandBuffer>& cb)
37 {
38 auto execute = [&]()
39 {
40 glQueryCounter(mQueryStartObj, GL_TIMESTAMP);
41 BS_CHECK_GL_ERROR();
42
43 setActive(true);
44 mEndIssued = false;
45 };
46
47 if (cb == nullptr)
48 execute();
49 else
50 {
51 SPtr<GLCommandBuffer> glCB = std::static_pointer_cast<GLCommandBuffer>(cb);
52 glCB->queueCommand(execute);
53 }
54 }
55
56 void GLTimerQuery::end(const SPtr<CommandBuffer>& cb)
57 {
58 auto execute = [&]()
59 {
60 glQueryCounter(mQueryEndObj, GL_TIMESTAMP);
61 BS_CHECK_GL_ERROR();
62
63 mEndIssued = true;
64 mFinalized = false;
65 };
66
67 if (cb == nullptr)
68 execute();
69 else
70 {
71 SPtr<GLCommandBuffer> glCB = std::static_pointer_cast<GLCommandBuffer>(cb);
72 glCB->queueCommand(execute);
73 }
74 }
75
76 bool GLTimerQuery::isReady() const
77 {
78 if (!mEndIssued)
79 return false;
80
81 GLint done = 0;
82 glGetQueryObjectiv(mQueryEndObj, GL_QUERY_RESULT_AVAILABLE, &done);
83 BS_CHECK_GL_ERROR();
84
85 return done == GL_TRUE;
86 }
87
88 float GLTimerQuery::getTimeMs()
89 {
90 if(!mFinalized && isReady())
91 {
92 finalize();
93 }
94
95 return mTimeDelta;
96 }
97
98 void GLTimerQuery::finalize()
99 {
100 mFinalized = true;
101
102 GLuint64 timeStart;
103 GLuint64 timeEnd;
104
105 glGetQueryObjectui64v(mQueryStartObj, GL_QUERY_RESULT, &timeStart);
106 BS_CHECK_GL_ERROR();
107
108 glGetQueryObjectui64v(mQueryEndObj, GL_QUERY_RESULT, &timeEnd);
109 BS_CHECK_GL_ERROR();
110
111 mTimeDelta = (timeEnd - timeStart) / 1000000.0f;
112 }
113}}