| 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 b1c9f23e4858f5a68ac1c1e3b161c956c02d56ee..93c54341dfe201fa5b5525bb7808a76fe95b865e 100644
|
| --- a/gpu/command_buffer/service/gpu_tracer.cc
|
| +++ b/gpu/command_buffer/service/gpu_tracer.cc
|
| @@ -59,45 +59,68 @@ void TraceOutputter::Trace(const std::string& name,
|
| ++local_trace_id_;
|
| }
|
|
|
| -GPUTrace::GPUTrace(const std::string& name)
|
| - : name_(name),
|
| - outputter_(NULL),
|
| - offset_(0),
|
| - end_time_(0),
|
| - end_requested_(false),
|
| - enabled_(false) {
|
| -}
|
| -
|
| GPUTrace::GPUTrace(scoped_refptr<Outputter> outputter,
|
| const std::string& name,
|
| - int64 offset)
|
| + int64 offset,
|
| + GpuTracerType tracer_type)
|
| : name_(name),
|
| outputter_(outputter),
|
| offset_(offset),
|
| start_time_(0),
|
| end_time_(0),
|
| - end_requested_(false),
|
| - enabled_(true) {
|
| - glGenQueries(2, queries_);
|
| + 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;
|
| + }
|
| }
|
|
|
| GPUTrace::~GPUTrace() {
|
| - if (enabled_)
|
| - glDeleteQueries(2, queries_);
|
| + switch (tracer_type_) {
|
| + case kTracerTypeInvalid:
|
| + break;
|
| +
|
| + case kTracerTypeARBTimer:
|
| + case kTracerTypeDisjointTimer:
|
| + glDeleteQueriesARB(2, queries_);
|
| + break;
|
| + }
|
| }
|
|
|
| void GPUTrace::Start() {
|
| TRACE_EVENT_COPY_ASYNC_BEGIN0(
|
| TRACE_DISABLED_BY_DEFAULT("gpu.service"), name().c_str(), this);
|
| - if (enabled_) {
|
| - glQueryCounter(queries_[0], GL_TIMESTAMP);
|
| +
|
| + switch (tracer_type_) {
|
| + case kTracerTypeInvalid:
|
| + break;
|
| +
|
| + case kTracerTypeARBTimer:
|
| + case kTracerTypeDisjointTimer:
|
| + // GL_TIMESTAMP and GL_TIMESTAMP_EXT both have the same value.
|
| + glQueryCounter(queries_[0], GL_TIMESTAMP);
|
| + break;
|
| }
|
| }
|
|
|
| void GPUTrace::End() {
|
| - if (enabled_) {
|
| - glQueryCounter(queries_[1], GL_TIMESTAMP);
|
| - end_requested_ = true;
|
| + 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;
|
| }
|
|
|
| TRACE_EVENT_COPY_ASYNC_END0(
|
| @@ -105,34 +128,36 @@ void GPUTrace::End() {
|
| }
|
|
|
| bool GPUTrace::IsAvailable() {
|
| - if (!enabled_)
|
| - return true;
|
| - else if (!end_requested_)
|
| - return false;
|
| + if (tracer_type_ != kTracerTypeInvalid) {
|
| + if (!end_requested_)
|
| + return false;
|
|
|
| - GLint done = 0;
|
| - glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
|
| - return !!done;
|
| + GLint done = 0;
|
| + glGetQueryObjectiv(queries_[1], GL_QUERY_RESULT_AVAILABLE, &done);
|
| + return !!done;
|
| + }
|
| +
|
| + return true;
|
| }
|
|
|
| void GPUTrace::Process() {
|
| - if (!enabled_)
|
| + if (tracer_type_ == kTracerTypeInvalid)
|
| return;
|
|
|
| DCHECK(IsAvailable());
|
|
|
| - GLuint64 timestamp;
|
| + 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, ×tamp);
|
| - start_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
|
| + glGetQueryObjectui64v(queries_[0], GL_QUERY_RESULT, &begin_stamp);
|
| + glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, &end_stamp);
|
|
|
| - glGetQueryObjectui64v(queries_[1], GL_QUERY_RESULT, ×tamp);
|
| - end_time_ = (timestamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
|
| -
|
| - glDeleteQueries(2, queries_);
|
| + start_time_ = (begin_stamp / base::Time::kNanosecondsPerMicrosecond) +
|
| + offset_;
|
| + end_time_ = (end_stamp / base::Time::kNanosecondsPerMicrosecond) + offset_;
|
| outputter_->Trace(name(), start_time_, end_time_);
|
| }
|
|
|
| @@ -144,13 +169,16 @@ GPUTracer::GPUTracer(gles2::GLES2Decoder* decoder)
|
| decoder_(decoder),
|
| timer_offset_(0),
|
| last_tracer_source_(kTraceGroupInvalid),
|
| - enabled_(false),
|
| + tracer_type_(kTracerTypeInvalid),
|
| gpu_timing_synced_(false),
|
| gpu_executing_(false),
|
| process_posted_(false) {
|
| - if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
|
| + if (gfx::g_driver_gl.ext.b_GL_EXT_disjoint_timer_query) {
|
| + tracer_type_ = kTracerTypeDisjointTimer;
|
| + outputter_ = TraceOutputter::Create("GL_EXT_disjoint_timer_query");
|
| + } else if (gfx::g_driver_gl.ext.b_GL_ARB_timer_query) {
|
| + tracer_type_ = kTracerTypeARBTimer;
|
| outputter_ = TraceOutputter::Create("GL_ARB_timer_query");
|
| - enabled_ = true;
|
| }
|
| }
|
|
|
| @@ -158,25 +186,19 @@ GPUTracer::~GPUTracer() {
|
| }
|
|
|
| bool GPUTracer::BeginDecoding() {
|
| - if (enabled_) {
|
| - if (*gpu_trace_dev_category) {
|
| - // Make sure timing is synced before tracing
|
| - if (!gpu_timing_synced_) {
|
| - CalculateTimerOffset();
|
| - gpu_timing_synced_ = true;
|
| - }
|
| - } else {
|
| - // If GPU device category is off, invalidate timing sync
|
| - gpu_timing_synced_ = false;
|
| - }
|
| - }
|
| -
|
| if (gpu_executing_)
|
| return false;
|
|
|
| + 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);
|
| + }
|
| +
|
| // 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++) {
|
| @@ -272,10 +294,10 @@ const std::string& GPUTracer::CurrentName() const {
|
| }
|
|
|
| scoped_refptr<GPUTrace> GPUTracer::CreateTrace(const std::string& name) {
|
| - if (enabled_ && *gpu_trace_dev_category)
|
| - return new GPUTrace(outputter_, name, timer_offset_);
|
| - else
|
| - return new GPUTrace(name);
|
| + GpuTracerType tracer_type = *gpu_trace_dev_category ? tracer_type_ :
|
| + kTracerTypeInvalid;
|
| +
|
| + return new GPUTrace(outputter_, name, timer_offset_, tracer_type);
|
| }
|
|
|
| void GPUTracer::Process() {
|
| @@ -285,11 +307,8 @@ void GPUTracer::Process() {
|
| }
|
|
|
| void GPUTracer::ProcessTraces() {
|
| - if (!enabled_) {
|
| - while (!traces_.empty() && traces_.front()->IsAvailable()) {
|
| - traces_.front()->Process();
|
| - traces_.pop_front();
|
| - }
|
| + if (tracer_type_ == kTracerTypeInvalid) {
|
| + traces_.clear();
|
| return;
|
| }
|
|
|
| @@ -302,6 +321,14 @@ 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();
|
| + }
|
| +
|
| while (!traces_.empty() && traces_.front()->IsAvailable()) {
|
| traces_.front()->Process();
|
| traces_.pop_front();
|
| @@ -314,23 +341,48 @@ void GPUTracer::ProcessTraces() {
|
| }
|
|
|
| void GPUTracer::CalculateTimerOffset() {
|
| - if (enabled_) {
|
| + if (tracer_type_ != kTracerTypeInvalid) {
|
| + // If GPU device category is off, invalidate timing sync.
|
| + if (*gpu_trace_dev_category == '\0') {
|
| + gpu_timing_synced_ = false;
|
| + return;
|
| + }
|
| +
|
| + if (gpu_timing_synced_)
|
| + return;
|
| +
|
| TRACE_EVENT0("gpu", "GPUTracer::CalculateTimerOffset");
|
|
|
| // NOTE(vmiura): It would be better to use glGetInteger64v, however
|
| // it's not available everywhere.
|
| GLuint64 gl_now = 0;
|
| GLuint query;
|
| + GLint disjoint_value = 0;
|
| +
|
| + if (tracer_type_ == kTracerTypeDisjointTimer) {
|
| + // Clear the disjoint bit before we do any queries.
|
| + glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
|
| + }
|
| +
|
| glFinish();
|
| - glGenQueries(1, &query);
|
| + glGenQueriesARB(1, &query);
|
| glQueryCounter(query, GL_TIMESTAMP);
|
| glFinish();
|
| +
|
| glGetQueryObjectui64v(query, GL_QUERY_RESULT, &gl_now);
|
| + glDeleteQueriesARB(1, &query);
|
| +
|
| + if (tracer_type_ == kTracerTypeDisjointTimer) {
|
| + glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value);
|
| + if (disjoint_value)
|
| + return;
|
| + }
|
| +
|
| base::TimeTicks system_now = base::TimeTicks::NowFromSystemTraceTime();
|
|
|
| gl_now /= base::Time::kNanosecondsPerMicrosecond;
|
| timer_offset_ = system_now.ToInternalValue() - gl_now;
|
| - glDeleteQueries(1, &query);
|
| + gpu_timing_synced_ = true;
|
| }
|
| }
|
|
|
|
|