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 "BsGLOcclusionQuery.h"
4#include "BsGLCommandBuffer.h"
5#include "Math/BsMath.h"
6#include "Profiling/BsRenderStats.h"
7
8namespace bs { namespace ct
9{
10 GLOcclusionQuery::GLOcclusionQuery(bool binary, UINT32 deviceIdx)
11 :OcclusionQuery(binary)
12 {
13 assert(deviceIdx == 0 && "Multiple GPUs not supported natively on OpenGL.");
14
15 glGenQueries(1, &mQueryObj);
16 BS_CHECK_GL_ERROR();
17
18 BS_INC_RENDER_STAT_CAT(ResCreated, RenderStatObject_Query);
19 }
20
21 GLOcclusionQuery::~GLOcclusionQuery()
22 {
23 glDeleteQueries(1, &mQueryObj);
24 BS_CHECK_GL_ERROR();
25
26 BS_INC_RENDER_STAT_CAT(ResDestroyed, RenderStatObject_Query);
27 }
28
29 void GLOcclusionQuery::begin(const SPtr<CommandBuffer>& cb)
30 {
31 auto execute = [&]()
32 {
33 glBeginQuery(mBinary ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED, mQueryObj);
34 BS_CHECK_GL_ERROR();
35
36 mNumSamples = 0;
37 mEndIssued = false;
38 setActive(true);
39 };
40
41 if (cb == nullptr)
42 execute();
43 else
44 {
45 SPtr<GLCommandBuffer> glCB = std::static_pointer_cast<GLCommandBuffer>(cb);
46 glCB->queueCommand(execute);
47 }
48 }
49
50 void GLOcclusionQuery::end(const SPtr<CommandBuffer>& cb)
51 {
52 auto execute = [&]()
53 {
54 glEndQuery(mBinary ? GL_ANY_SAMPLES_PASSED : GL_SAMPLES_PASSED);
55 BS_CHECK_GL_ERROR();
56
57 mEndIssued = true;
58 mFinalized = false;
59 };
60
61 if (cb == nullptr)
62 execute();
63 else
64 {
65 SPtr<GLCommandBuffer> glCB = std::static_pointer_cast<GLCommandBuffer>(cb);
66 glCB->queueCommand(execute);
67 }
68 }
69
70 bool GLOcclusionQuery::isReady() const
71 {
72 if (!mEndIssued)
73 return false;
74
75 GLint done = 0;
76 glGetQueryObjectiv(mQueryObj, GL_QUERY_RESULT_AVAILABLE, &done);
77 BS_CHECK_GL_ERROR();
78
79 return done == GL_TRUE;
80 }
81
82 UINT32 GLOcclusionQuery::getNumSamples()
83 {
84 if (!mFinalized && isReady())
85 {
86 finalize();
87 }
88
89 return mNumSamples;
90 }
91
92 void GLOcclusionQuery::finalize()
93 {
94 mFinalized = true;
95
96 if (mBinary)
97 {
98 GLuint anyPassed = GL_FALSE;
99 glGetQueryObjectuiv(mQueryObj, GL_QUERY_RESULT, &anyPassed);
100 BS_CHECK_GL_ERROR();
101
102 mNumSamples = anyPassed == GL_TRUE ? 1 : 0;
103 }
104 else
105 {
106 GLuint numSamples = 0;
107 glGetQueryObjectuiv(mQueryObj, GL_QUERY_RESULT, &numSamples);
108 BS_CHECK_GL_ERROR();
109
110 mNumSamples = (UINT32)numSamples;
111 }
112 }
113}}