Ion
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
gpuprofiler.cc
Go to the documentation of this file.
1 
19 
22 
23 namespace ion {
24 namespace gfxprofile {
25 
28  return profiler;
29 }
30 
32  : manager_(ion::profile::GetCallTraceManager()),
33  enable_gpu_tracing_("enable_gpu_tracing", false),
34  gl_timer_offset_ns_(0) {
35 }
36 
38  : manager_(manager),
39  enable_gpu_tracing_("enable_gpu_tracing", false),
40  gl_timer_offset_ns_(0) {
41 }
42 
44 
46  const ion::gfx::GraphicsManagerPtr& gfx_mgr) const {
47  if (!gfx_mgr->IsExtensionSupported("GL_EXT_disjoint_timer_query")) {
48  return false;
49  }
50 
51  GLint bits = 0;
52  gfx_mgr->GetQueryiv(GL_TIMESTAMP_EXT, GL_QUERY_COUNTER_BITS_EXT, &bits);
53  if (bits == 0) {
54  return false;
55  }
56 
57  return true;
58 }
59 
61  const ion::gfx::GraphicsManagerPtr& gfx_mgr) {
62  if (!IsGpuProfilingSupported(gfx_mgr)) {
63  return;
64  }
65 
66  graphics_manager_ = gfx_mgr;
67 
68  SyncGlTimebase();
69 }
70 
71 GLuint GpuProfiler::TryAllocateGlQueryId() {
73  if (!gfx_mgr) {
74  return 0;
75  }
76 
77  GLuint query_id = 0;
78  if (gl_timer_query_id_pool_.empty()) {
79  DCHECK(gfx_mgr);
80  gfx_mgr->GenQueries(1, &query_id);
81  } else {
82  query_id = gl_timer_query_id_pool_.top();
83  gl_timer_query_id_pool_.pop();
84  }
85  return query_id;
86 }
87 
88 void GpuProfiler::EnterGlScope(uint32 id) {
90  if (!gfx_mgr) {
91  return;
92  }
93 
94  GLuint query_id = TryAllocateGlQueryId();
95  if (query_id != 0) {
96  gfx_mgr->QueryCounter(query_id, GL_TIMESTAMP_EXT);
97  pending_gpu_queries_.push_back(GpuTimerQuery(
98  manager_->GetTimeInNs(), id, query_id,
99  GpuTimerQuery::kQueryBeginScope));
100  }
101 }
102 
105  if (!gfx_mgr) {
106  return;
107  }
108 
109  GLuint query_id = TryAllocateGlQueryId();
110  if (query_id != 0) {
111  gfx_mgr->QueryCounter(query_id, GL_TIMESTAMP_EXT);
112  pending_gpu_queries_.push_back(
113  GpuTimerQuery(manager_->GetTimeInNs(), 0, query_id,
114  GpuTimerQuery::kQueryEndScope));
115  }
116 }
117 
118 void GpuProfiler::SyncGlTimebase() {
120  if (!gfx_mgr) {
121  return;
122  }
123 
128  GLint disjoint = 0;
129  gfx_mgr->GetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint);
130 
133  int attempts_remaining = 3;
134  do {
135  GLint64 gl_timestamp = 0;
136  gfx_mgr->GetInteger64v(GL_TIMESTAMP_EXT, &gl_timestamp);
137 
139  int64 cpu_timebase_ns = static_cast<int64>(manager_->GetTimeInNs());
140 
141  disjoint = 0;
142  gfx_mgr->GetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint);
143  if (!disjoint) {
144  gl_timer_offset_ns_ = cpu_timebase_ns - gl_timestamp;
145  break;
146  }
147  LOG(WARNING) << "Skipping disjoint GPU timestamp";
148  } while (--attempts_remaining > 0);
149 
150  if (attempts_remaining == 0) {
151  LOG(ERROR) << "Failed to sync GL timebase due to disjoint results";
152  gl_timer_offset_ns_ = 0;
153  }
154 }
155 
158  if (!gfx_mgr) {
159  return;
160  }
161 
164 
165  GLuint begin_frame_id = TryAllocateGlQueryId();
166  if (begin_frame_id != 0) {
167  gfx_mgr->QueryCounter(begin_frame_id, GL_TIMESTAMP_EXT);
168  pending_gpu_queries_.push_back(
169  GpuTimerQuery(manager_->GetTimeInNs(), 0, begin_frame_id,
170  GpuTimerQuery::kQueryBeginFrame));
171  }
172 
173  bool has_checked_disjoint = false;
174  bool was_disjoint = false;
175  for (;;) {
176  if (pending_gpu_queries_.empty()) {
178  return;
179  }
180 
181  GpuTimerQuery query = pending_gpu_queries_.front();
182 
183  GLint available = 0;
184  gfx_mgr->GetQueryObjectiv(query.gl_query_id,
185  GL_QUERY_RESULT_AVAILABLE_EXT, &available);
186  if (!available) {
188  return;
189  }
190 
192  pending_gpu_queries_.pop_front();
193  gl_timer_query_id_pool_.push(query.gl_query_id);
194 
195  if (!has_checked_disjoint) {
199  has_checked_disjoint = true;
200  GLint disjoint_occurred = 0;
201  gfx_mgr->GetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_occurred);
202  was_disjoint = !!disjoint_occurred;
203  if (was_disjoint) {
204  LOG(WARNING) << "Skipping disjoint GPU events";
205  }
206  }
207 
208  if (was_disjoint) {
209  continue;
210  }
211 
212  GLint64 timestamp_ns = 0;
213  gfx_mgr->GetQueryObjecti64v(query.gl_query_id,
214  GL_QUERY_RESULT_EXT, &timestamp_ns);
215 
216  uint64 adjusted_timestamp_ns = timestamp_ns + gl_timer_offset_ns_;
217 
218  if (query.query_type == GpuTimerQuery::kQueryBeginFrame ||
219  query.query_type == GpuTimerQuery::kQueryBeginScope) {
220  if (adjusted_timestamp_ns < query.cpu_timestamp_ns) {
222  gl_timer_offset_ns_ += query.cpu_timestamp_ns - adjusted_timestamp_ns;
223  adjusted_timestamp_ns = query.cpu_timestamp_ns;
224  }
225  }
226 
227  uint32 adjusted_timestamp_us =
228  static_cast<uint32>(adjusted_timestamp_ns / 1000ll);
229  switch (query.query_type) {
230  case GpuTimerQuery::kQueryBeginFrame:
231  break;
232  case GpuTimerQuery::kQueryBeginScope:
233  recorder->EnterScopeAtTime(adjusted_timestamp_us, query.scope_event_id);
234  break;
235  case GpuTimerQuery::kQueryEndScope:
236  recorder->LeaveScopeAtTime(adjusted_timestamp_us);
237  break;
238  }
239  }
240 }
241 
242 } // namespace gfxprofile
243 } // namespace ion
int64_t GLint64
Definition: glheaders.h:130
GraphicsManager manages the graphics library for an application.
bool IsGpuProfilingSupported(const ion::gfx::GraphicsManagerPtr &gfx_mgr) const
Definition: gpuprofiler.cc:45
#define ION_DECLARE_SAFE_STATIC_POINTER(type, variable)
Declare a static non-array pointer and calls a default constructor.
Class for recording frame events.
Definition: tracerecorder.h:42
CallTraceManager * GetCallTraceManager()
Get the global, static instance of CallTraceManager.
Definition: profiling.cc:25
#define DCHECK(expr)
Definition: logging.h:331
void EnterGlScope(uint32 id)
Records the beginning of a scoped GL trace event.
Definition: gpuprofiler.cc:88
#define LOG(severity)
Logs the streamed message unconditionally with a severity of severity.
Definition: logging.h:216
static GpuProfiler * Get()
Gets the GpuProfiler singleton instance.
Definition: gpuprofiler.cc:26
void EnterScopeAtTime(uint32 timestamp, int event_id)
Same as EnterScope, but with specified timestamp.
framebuffer alpha dfactor const GLvoid usage alpha const GLvoid data border const GLuint buffers const GLuint renderbuffers count renderbuffer GLuint framebuffers GLsizei GLint GLenum GLchar name GLsizei GLuint shaders GLint data GLsizei GLchar info_log GLint params GLint GLint precision GLint params GLint params GLint params GLfloat params GLvoid pointer height height const GLchar const GLint length mask dppass param param const GLvoid data const GLint1 value const GLfloat2 value v2 v2 v3 v3 const GLmatrix2 value const GLmatrix4 value v1 v2 v3 const GLvoid pointer GLsizei GLchar label const GLchar marker const void userParam const GLchar buf void params height const GLuint1 value const GLuint2 value const GLuint3 value const GLuint4 value void image primCount divisor length size sampler GLuint samplers GLint params const GLfloat params const GLint params flags timeout const GLvoid data const GLvoid pixels fixed_sample_locations GLfloat val height fixed_sample_locations primitive_mode const GLuint ids GLsizei GLsizei GLenum GLchar name const GLchar buffer_mode GLuint arrays GLint params GetQueryObjectiv
#define GL_GPU_DISJOINT_EXT
Definition: glheaders.h:405
uint32 id
#define GL_QUERY_COUNTER_BITS_EXT
Definition: glheaders.h:639
#define GL_QUERY_RESULT_EXT
Definition: glheaders.h:648
void SetGraphicsManager(const gfx::GraphicsManagerPtr &gfx_mgr)
Sets the GraphicsManager that is required for performing GPU tracing via OpenGL.
Definition: gpuprofiler.cc:60
Singleton class that augments CallTraceManager with GPU tracing support.
Definition: gpuprofiler.h:55
TraceRecorder * GetNamedTraceRecorder(NamedTraceRecorderType name)
Gets the TraceRecorder instance specific to the current thread of the given name. ...
Manages call trace recording for visualization in Web Tracing Framework (WTF) format.
gfx::GraphicsManager * GetGraphicsManagerOrNull() const
Gets the GraphicsManager if GPU tracing is enabled.
Definition: gpuprofiler.h:80
#define GL_TIMESTAMP_EXT
Definition: glheaders.h:1074
A SharedPtr is a smart shared pointer to an instance of some class that implements reference counting...
Definition: sharedptr.h:60
void LeaveScopeAtTime(uint32 timestamp)
Same as LeaveScope, but with specified timestamp.
void LeaveGlScope()
Records the end of a scoped GL trace event.
Definition: gpuprofiler.cc:103
#define GL_QUERY_RESULT_AVAILABLE_EXT
Definition: glheaders.h:645
void PollGlTimerQueries()
Polls (non-blocking) for completed GL timer query data and adds events into the trace buffer...
Definition: gpuprofiler.cc:156
uint64 GetTimeInNs() const
Returns the time in nanoseconds, relative to the timebase.