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 | |
8 | namespace 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 | }} |