Index: gpu/command_buffer/service/gpu_tracer.cc |
diff --git a/gpu/command_buffer/service/gpu_tracer.cc b/gpu/command_buffer/service/gpu_tracer.cc |
index 72b29ddcfd7d12e010ef56c71a50c3ca32928a10..6bedb7f00fc30e0714b059c13b74b172ac8ab537 100644 |
--- a/gpu/command_buffer/service/gpu_tracer.cc |
+++ b/gpu/command_buffer/service/gpu_tracer.cc |
@@ -20,16 +20,6 @@ namespace gles2 { |
static const unsigned int kProcessInterval = 16; |
static TraceOutputter* g_outputter_thread = NULL; |
-CPUTime::CPUTime() { |
-} |
- |
-int64 CPUTime::GetCurrentTime() { |
- return base::TimeTicks::NowFromSystemTraceTime().ToInternalValue(); |
-} |
- |
-CPUTime::~CPUTime() { |
-} |
- |
TraceMarker::TraceMarker(const std::string& category, const std::string& name) |
: category_(category), |
name_(name), |
@@ -90,122 +80,53 @@ void TraceOutputter::TraceServiceEnd(const std::string& category, |
} |
GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter, |
- scoped_refptr<CPUTime> cpu_time, |
+ gpu::GPUTiming* gpu_timing, |
const std::string& category, |
const std::string& name, |
- int64 offset, |
- GpuTracerType tracer_type) |
+ const bool enabled) |
: category_(category), |
name_(name), |
outputter_(outputter), |
- cpu_time_(cpu_time), |
- offset_(offset), |
- start_time_(0), |
- end_time_(0), |
- tracer_type_(tracer_type), |
- end_requested_(false) { |
- memset(queries_, 0, sizeof(queries_)); |
- switch (tracer_type_) { |
- case kTracerTypeARBTimer: |
- case kTracerTypeDisjointTimer: |
- glGenQueriesARB(2, queries_); |
- break; |
- |
- default: |
- tracer_type_ = kTracerTypeInvalid; |
+ enabled_(enabled) { |
+ if (gpu_timing->IsAvailable()) { |
+ gpu_timer_.reset(new GPUTimer(gpu_timing)); |
} |
} |
GPUTrace::~GPUTrace() { |
- switch (tracer_type_) { |
- case kTracerTypeInvalid: |
- break; |
- |
- case kTracerTypeARBTimer: |
- case kTracerTypeDisjointTimer: |
- glDeleteQueriesARB(2, queries_); |
- break; |
- } |
} |
void GPUTrace::Start(bool trace_service) { |
if (trace_service) { |
outputter_->TraceServiceBegin(category_, name_); |
} |
- |
- switch (tracer_type_) { |
- case kTracerTypeInvalid: |
- break; |
- |
- case kTracerTypeDisjointTimer: |
- // For the disjoint timer, GPU idle time does not seem to increment the |
- // internal counter. We must calculate the offset before any query. |
- // glGetInteger64v is supported under ES3 which we check for before using |
- // the kTracerTypeDisjointTimer. |
- { |
- GLint64 gl_now = 0; |
- glGetInteger64v(GL_TIMESTAMP, &gl_now); |
- offset_ = cpu_time_->GetCurrentTime() - |
- gl_now / base::Time::kNanosecondsPerMicrosecond; |
- } |
- // Intentionally fall through to kTracerTypeARBTimer case.xs |
- case kTracerTypeARBTimer: |
- // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. |
- glQueryCounter(queries_[0], GL_TIMESTAMP); |
- break; |
+ if (gpu_timer_.get()) { |
+ gpu_timer_->Start(); |
} |
} |
void GPUTrace::End(bool tracing_service) { |
- end_requested_ = true; |
- switch (tracer_type_) { |
- case kTracerTypeInvalid: |
- break; |
- |
- case kTracerTypeARBTimer: |
- case kTracerTypeDisjointTimer: |
- // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value. |
- glQueryCounter(queries_[1], GL_TIMESTAMP); |
- break; |
+ if (gpu_timer_.get()) { |
+ gpu_timer_->End(); |
} |
- |
if (tracing_service) { |
outputter_->TraceServiceEnd(category_, name_); |
} |
} |
bool GPUTrace::IsAvailable() { |
- if (tracer_type_ != kTracerTypeInvalid) { |
- if (!end_requested_) |
- return false; |
- |
- GLint done = 0; |
- glGetQueryObjectivARB(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done); |
- return !!done; |
- } |
- |
- return true; |
+ return !gpu_timer_.get() || gpu_timer_->IsAvailable(); |
} |
void GPUTrace::Process() { |
- if (tracer_type_ == kTracerTypeInvalid) |
- return; |
+ if (gpu_timer_.get()) { |
+ DCHECK(IsAvailable()); |
- DCHECK(IsAvailable()); |
- |
- GLuint64 begin_stamp = 0; |
- GLuint64 end_stamp = 0; |
- |
- // TODO(dsinclair): It's possible for the timer to wrap during the start/end. |
- // We need to detect if the end is less then the start and correct for the |
- // wrapping. |
- glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp); |
- glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp); |
- |
- start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) + |
- offset_; |
- end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_; |
- outputter_->TraceDevice(category_, name_, start_time_, end_time_); |
+ int64 start = 0; |
+ int64 end = 0; |
+ gpu_timer_->GetStartEndTimestamps(&start, &end); |
+ outputter_->TraceDevice(category_, name_, start, end); |
+ } |
} |
GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) |
@@ -214,9 +135,7 @@ GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder) |
gpu_trace_dev_category(TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED( |
TRACE_DISABLED_BY_DEFAULT("gpu.device"))), |
decoder_(decoder), |
- timer_offset_(0), |
- tracer_type_(kTracerTypeInvalid), |
- gpu_timing_synced_(false), |
+ gpu_timing_(), |
gpu_executing_(false), |
process_posted_(false) { |
} |
@@ -229,43 +148,25 @@ bool GPUTracer::BeginDecoding() { |
return false; |
if (outputter_ == NULL) { |
- tracer_type_ = DetermineTracerType(); |
- const char* tracer_type_name = "Unknown"; |
- switch (tracer_type_) { |
- case kTracerTypeDisjointTimer: |
- tracer_type_name = "GL_EXT_disjoint_timer_query"; |
- break; |
- case kTracerTypeARBTimer: |
- tracer_type_name = "GL_ARB_timer_query"; |
- break; |
- |
- default: |
- break; |
- } |
- |
- outputter_ = CreateOutputter(tracer_type_name); |
+ outputter_ = CreateOutputter(gpu_timing_.GetTimerTypeName()); |
+ gpu_timing_.Initialize(decoder_->GetGLContext()); |
} |
- if (cpu_time_ == NULL) { |
- cpu_time_ = CreateCPUTime(); |
+ if (*gpu_trace_dev_category == '\0') { |
+ // If GPU device category is off, invalidate timing sync. |
+ gpu_timing_.InvalidateTimerOffset(); |
} |
- CalculateTimerOffset(); |
gpu_executing_ = true; |
- |
if (IsTracing()) { |
- // Reset disjoint bit for the disjoint timer. |
- if (tracer_type_ == kTracerTypeDisjointTimer) { |
- GLint disjoint_value = 0; |
- glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
- } |
- |
+ gpu_timing_.CheckAndResetTimerErrors(); |
// Begin a Trace for all active markers |
for (int n = 0; n < NUM_TRACER_SOURCES; n++) { |
for (size_t i = 0; i < markers_[n].size(); i++) { |
TraceMarker& trace_marker = markers_[n][i]; |
- trace_marker.trace_ = CreateTrace(trace_marker.category_, |
- trace_marker.name_); |
+ trace_marker.trace_ = |
+ new GPUTrace(outputter_, &gpu_timing_, trace_marker.category_, |
+ trace_marker.name_, *gpu_trace_dev_category != 0); |
trace_marker.trace_->Start(*gpu_trace_srv_category != 0); |
} |
} |
@@ -313,7 +214,8 @@ bool GPUTracer::Begin(const std::string& category, const std::string& name, |
// Create trace |
if (IsTracing()) { |
- scoped_refptr<GPUTrace> trace = CreateTrace(category, name); |
+ scoped_refptr<GPUTrace> trace = new GPUTrace( |
+ outputter_, &gpu_timing_, category, name, *gpu_trace_dev_category != 0); |
trace->Start(*gpu_trace_srv_category != 0); |
markers_[source].back().trace_ = trace; |
} |
@@ -367,38 +269,10 @@ const std::string& GPUTracer::CurrentName(GpuTracerSource source) const { |
return base::EmptyString(); |
} |
-scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& category, |
- const std::string& name) { |
- GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ : |
- kTracerTypeInvalid; |
- |
- return new GPUTrace(outputter_, cpu_time_, category, name, |
- timer_offset_, tracer_type); |
-} |
- |
scoped_refptr<Outputter> GPUTracer::CreateOutputter(const std::string& name) { |
return TraceOutputter::Create(name); |
} |
-scoped_refptr<CPUTime> GPUTracer::CreateCPUTime() { |
- return new CPUTime(); |
-} |
- |
-GpuTracerType GPUTracer::DetermineTracerType() { |
- ContextGroup* context_group = decoder_->GetContextGroup(); |
- const gpu::gles2::FeatureInfo* feature_info = context_group->feature_info(); |
- const gfx::GLVersionInfo& version_info = feature_info->gl_version_info(); |
- |
- if (version_info.is_es3 && |
- gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) { |
- return kTracerTypeDisjointTimer; |
- } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) { |
- return kTracerTypeARBTimer; |
- } |
- |
- return kTracerTypeInvalid; |
-} |
- |
void GPUTracer::PostTask() { |
base::MessageLoop::current()->PostDelayedTask( |
FROM_HERE, |
@@ -413,7 +287,7 @@ void GPUTracer::Process() { |
} |
void GPUTracer::ProcessTraces() { |
- if (tracer_type_ == kTracerTypeInvalid) { |
+ if (!gpu_timing_.IsAvailable()) { |
traces_.clear(); |
return; |
} |
@@ -427,13 +301,10 @@ void GPUTracer::ProcessTraces() { |
return; |
} |
- // Check if disjoint operation has occurred, discard ongoing traces if so. |
- if (tracer_type_ == kTracerTypeDisjointTimer) { |
- GLint disjoint_value = 0; |
- glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
- if (disjoint_value) |
- traces_.clear(); |
- } |
+ // Check if timers are still valid (e.g: a disjoint operation |
+ // might have occurred.) |
+ if (gpu_timing_.CheckAndResetTimerErrors()) |
+ traces_.clear(); |
while (!traces_.empty() && traces_.front()->IsAvailable()) { |
traces_.front()->Process(); |
@@ -446,24 +317,6 @@ void GPUTracer::ProcessTraces() { |
traces_.clear(); |
} |
-void GPUTracer::CalculateTimerOffset() { |
- if (tracer_type_ != kTracerTypeInvalid) { |
- if (*gpu_trace_dev_category == '\0') { |
- // If GPU device category is off, invalidate timing sync. |
- gpu_timing_synced_ = false; |
- } else if (!gpu_timing_synced_ && tracer_type_ == kTracerTypeARBTimer) { |
- TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset"); |
- |
- // ARB Timer is written for OpenGL 3.2 which contains glGetInteger64v(). |
- GLint64 gl_now = 0; |
- glGetInteger64v(GL_TIMESTAMP, &gl_now); |
- timer_offset_ = cpu_time_->GetCurrentTime() - |
- gl_now / base::Time::kNanosecondsPerMicrosecond; |
- gpu_timing_synced_ = true; |
- } |
- } |
-} |
- |
void GPUTracer::IssueProcessTask() { |
if (traces_.empty() || process_posted_) |
return; |