| OLD | NEW |
| 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/gl/gpu_timing.h" | 5 #include "ui/gl/gpu_timing.h" |
| 6 | 6 |
| 7 #include "base/time/time.h" | 7 #include "base/time/time.h" |
| 8 #include "ui/gl/gl_bindings.h" | 8 #include "ui/gl/gl_bindings.h" |
| 9 #include "ui/gl/gl_context.h" | 9 #include "ui/gl/gl_context.h" |
| 10 #include "ui/gl/gl_version_info.h" | 10 #include "ui/gl/gl_version_info.h" |
| 11 | 11 |
| 12 namespace gfx { | 12 namespace gfx { |
| 13 | 13 |
| 14 class TimeElapsedTimerQuery; |
| 15 class TimerQuery; |
| 16 |
| 14 int64_t NanoToMicro(uint64_t nano_seconds) { | 17 int64_t NanoToMicro(uint64_t nano_seconds) { |
| 15 const uint64_t up = nano_seconds + base::Time::kNanosecondsPerMicrosecond / 2; | 18 const uint64_t up = nano_seconds + base::Time::kNanosecondsPerMicrosecond / 2; |
| 16 return static_cast<int64_t>(up / base::Time::kNanosecondsPerMicrosecond); | 19 return static_cast<int64_t>(up / base::Time::kNanosecondsPerMicrosecond); |
| 17 } | 20 } |
| 18 | 21 |
| 19 class GPUTimingImpl : public GPUTiming { | 22 class GPUTimingImpl : public GPUTiming { |
| 20 public: | 23 public: |
| 21 GPUTimingImpl(GLContextReal* context); | 24 GPUTimingImpl(GLContextReal* context); |
| 22 ~GPUTimingImpl() override; | 25 ~GPUTimingImpl() override; |
| 23 | 26 |
| (...skipping 282 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 306 DCHECK(context); | 309 DCHECK(context); |
| 307 const GLVersionInfo* version_info = context->GetVersionInfo(); | 310 const GLVersionInfo* version_info = context->GetVersionInfo(); |
| 308 DCHECK(version_info); | 311 DCHECK(version_info); |
| 309 if (version_info->is_es3 && // glGetInteger64v is supported under ES3. | 312 if (version_info->is_es3 && // glGetInteger64v is supported under ES3. |
| 310 context->HasExtension("GL_EXT_disjoint_timer_query")) { | 313 context->HasExtension("GL_EXT_disjoint_timer_query")) { |
| 311 timer_type_ = GPUTiming::kTimerTypeDisjoint; | 314 timer_type_ = GPUTiming::kTimerTypeDisjoint; |
| 312 } else if (context->HasExtension("GL_ARB_timer_query")) { | 315 } else if (context->HasExtension("GL_ARB_timer_query")) { |
| 313 timer_type_ = GPUTiming::kTimerTypeARB; | 316 timer_type_ = GPUTiming::kTimerTypeARB; |
| 314 } else if (context->HasExtension("GL_EXT_timer_query")) { | 317 } else if (context->HasExtension("GL_EXT_timer_query")) { |
| 315 timer_type_ = GPUTiming::kTimerTypeEXT; | 318 timer_type_ = GPUTiming::kTimerTypeEXT; |
| 319 force_time_elapsed_query_ = true; |
| 316 } | 320 } |
| 317 } | 321 } |
| 318 | 322 |
| 319 GPUTimingImpl::~GPUTimingImpl() { | 323 GPUTimingImpl::~GPUTimingImpl() { |
| 320 } | 324 } |
| 321 | 325 |
| 322 uint32_t GPUTimingImpl::GetDisjointCount() { | 326 uint32_t GPUTimingImpl::GetDisjointCount() { |
| 323 if (timer_type_ == GPUTiming::kTimerTypeDisjoint) { | 327 if (timer_type_ == GPUTiming::kTimerTypeDisjoint) { |
| 324 GLint disjoint_value = 0; | 328 GLint disjoint_value = 0; |
| 325 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); | 329 glGetIntegerv(GL_GPU_DISJOINT_EXT, &disjoint_value); |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 368 queries_.back().get())->EndQuery(this, result); | 372 queries_.back().get())->EndQuery(this, result); |
| 369 } else { | 373 } else { |
| 370 // Simply end the query and reset the current offset | 374 // Simply end the query and reset the current offset |
| 371 DCHECK(GetLastElapsedQuery().get()); | 375 DCHECK(GetLastElapsedQuery().get()); |
| 372 GetLastElapsedQuery()->EndQuery(this, result); | 376 GetLastElapsedQuery()->EndQuery(this, result); |
| 373 DCHECK(GetLastElapsedQuery().get() == nullptr); | 377 DCHECK(GetLastElapsedQuery().get() == nullptr); |
| 374 } | 378 } |
| 375 } | 379 } |
| 376 | 380 |
| 377 scoped_refptr<QueryResult> GPUTimingImpl::DoTimeStampQuery() { | 381 scoped_refptr<QueryResult> GPUTimingImpl::DoTimeStampQuery() { |
| 378 DCHECK(timer_type_ == GPUTiming::kTimerTypeDisjoint || | 382 DCHECK(timer_type_ != GPUTiming::kTimerTypeInvalid); |
| 379 timer_type_ == GPUTiming::kTimerTypeARB); | |
| 380 | 383 |
| 381 if (force_time_elapsed_query_) { | 384 if (force_time_elapsed_query_) { |
| 382 // Replace with elapsed timer queries instead. | 385 // Replace with elapsed timer queries instead. |
| 383 scoped_refptr<QueryResult> result = BeginElapsedTimeQuery(); | 386 scoped_refptr<QueryResult> result = BeginElapsedTimeQuery(); |
| 384 EndElapsedTimeQuery(result); | 387 EndElapsedTimeQuery(result); |
| 385 return result; | 388 return result; |
| 386 } | 389 } |
| 387 | 390 |
| 388 queries_.push_back(new TimeStampTimerQuery(next_timer_query_id_++)); | 391 queries_.push_back(new TimeStampTimerQuery(next_timer_query_id_++)); |
| 389 return static_cast<TimeStampTimerQuery*>(queries_.back().get())->DoQuery(); | 392 return static_cast<TimeStampTimerQuery*>(queries_.back().get())->DoQuery(); |
| (...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 460 } | 463 } |
| 461 | 464 |
| 462 GPUTiming::~GPUTiming() { | 465 GPUTiming::~GPUTiming() { |
| 463 } | 466 } |
| 464 | 467 |
| 465 GPUTimer::~GPUTimer() { | 468 GPUTimer::~GPUTimer() { |
| 466 } | 469 } |
| 467 | 470 |
| 468 void GPUTimer::Destroy(bool have_context) { | 471 void GPUTimer::Destroy(bool have_context) { |
| 469 if (have_context) { | 472 if (have_context) { |
| 470 if (!end_requested_) { | 473 if (timer_state_ == kTimerState_WaitingForEnd) { |
| 471 DCHECK(gpu_timing_client_->gpu_timing_); | 474 DCHECK(gpu_timing_client_->gpu_timing_); |
| 472 DCHECK(elapsed_timer_result_.get()); | 475 DCHECK(elapsed_timer_result_.get()); |
| 473 gpu_timing_client_->gpu_timing_->EndElapsedTimeQuery( | 476 gpu_timing_client_->gpu_timing_->EndElapsedTimeQuery( |
| 474 elapsed_timer_result_); | 477 elapsed_timer_result_); |
| 475 } | 478 } |
| 476 } | 479 } |
| 477 } | 480 } |
| 478 | 481 |
| 482 void GPUTimer::Reset() { |
| 483 // We can reset from any state other than when a Start() is waiting for End(). |
| 484 DCHECK(timer_state_ != kTimerState_WaitingForEnd); |
| 485 time_stamp_result_ = nullptr; |
| 486 elapsed_timer_result_ = nullptr; |
| 487 timer_state_ = kTimerState_Ready; |
| 488 } |
| 489 |
| 490 void GPUTimer::QueryTimeStamp() { |
| 491 DCHECK(gpu_timing_client_->gpu_timing_); |
| 492 Reset(); |
| 493 time_stamp_result_ = gpu_timing_client_->gpu_timing_->DoTimeStampQuery(); |
| 494 timer_state_ = kTimerState_WaitingForResult; |
| 495 } |
| 496 |
| 479 void GPUTimer::Start() { | 497 void GPUTimer::Start() { |
| 480 DCHECK(gpu_timing_client_->gpu_timing_); | 498 DCHECK(gpu_timing_client_->gpu_timing_); |
| 499 Reset(); |
| 481 if (!use_elapsed_timer_) | 500 if (!use_elapsed_timer_) |
| 482 time_stamp_result_ = gpu_timing_client_->gpu_timing_->DoTimeStampQuery(); | 501 time_stamp_result_ = gpu_timing_client_->gpu_timing_->DoTimeStampQuery(); |
| 483 | 502 |
| 484 elapsed_timer_result_ = | 503 elapsed_timer_result_ = |
| 485 gpu_timing_client_->gpu_timing_->BeginElapsedTimeQuery(); | 504 gpu_timing_client_->gpu_timing_->BeginElapsedTimeQuery(); |
| 505 timer_state_ = kTimerState_WaitingForEnd; |
| 486 } | 506 } |
| 487 | 507 |
| 488 void GPUTimer::End() { | 508 void GPUTimer::End() { |
| 509 DCHECK(timer_state_ == kTimerState_WaitingForEnd); |
| 489 DCHECK(elapsed_timer_result_.get()); | 510 DCHECK(elapsed_timer_result_.get()); |
| 490 end_requested_ = true; | |
| 491 gpu_timing_client_->gpu_timing_->EndElapsedTimeQuery(elapsed_timer_result_); | 511 gpu_timing_client_->gpu_timing_->EndElapsedTimeQuery(elapsed_timer_result_); |
| 512 timer_state_ = kTimerState_WaitingForResult; |
| 492 } | 513 } |
| 493 | 514 |
| 494 bool GPUTimer::IsAvailable() { | 515 bool GPUTimer::IsAvailable() { |
| 495 if (!end_requested_) | 516 if (timer_state_ == kTimerState_WaitingForResult) { |
| 496 return false; | 517 // Elapsed timer are only used during start/end queries and always after |
| 497 if (!end_available_) { | 518 // the timestamp query. Otherwise only the timestamp is used. |
| 498 DCHECK(elapsed_timer_result_.get()); | 519 scoped_refptr<QueryResult> result = |
| 499 if (elapsed_timer_result_->IsAvailable()) { | 520 elapsed_timer_result_.get() ? |
| 500 end_available_ = true; | 521 elapsed_timer_result_ : |
| 522 time_stamp_result_; |
| 523 |
| 524 DCHECK(result.get()); |
| 525 if (result->IsAvailable()) { |
| 526 timer_state_ = kTimerState_ResultAvailable; |
| 501 } else { | 527 } else { |
| 502 gpu_timing_client_->gpu_timing_->UpdateQueryResults(); | 528 gpu_timing_client_->gpu_timing_->UpdateQueryResults(); |
| 503 end_available_ = elapsed_timer_result_->IsAvailable(); | 529 if (result->IsAvailable()) |
| 530 timer_state_ = kTimerState_ResultAvailable; |
| 504 } | 531 } |
| 505 } | 532 } |
| 506 return end_available_; | 533 |
| 534 return (timer_state_ == kTimerState_ResultAvailable); |
| 507 } | 535 } |
| 508 | 536 |
| 509 void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) { | 537 void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) { |
| 510 DCHECK(start && end); | 538 DCHECK(start && end); |
| 511 DCHECK(elapsed_timer_result_.get()); | 539 DCHECK(elapsed_timer_result_.get() || time_stamp_result_.get()); |
| 512 DCHECK(IsAvailable()); | 540 DCHECK(IsAvailable()); |
| 513 if (time_stamp_result_.get()) { | 541 const int64_t time_stamp = time_stamp_result_.get() ? |
| 514 DCHECK(time_stamp_result_->IsAvailable()); | 542 time_stamp_result_->GetStartValue() : |
| 515 const int64_t time_stamp = time_stamp_result_->GetStartValue(); | 543 elapsed_timer_result_->GetStartValue(); |
| 516 *start = time_stamp; | 544 const int64_t elapsed_time = elapsed_timer_result_.get() ? |
| 517 *end = time_stamp + elapsed_timer_result_->GetDelta(); | 545 elapsed_timer_result_->GetDelta() : |
| 518 } else { | 546 0; |
| 519 // Use estimation from elasped timer results. | 547 |
| 520 *start = elapsed_timer_result_->GetStartValue(); | 548 *start = time_stamp; |
| 521 *end = elapsed_timer_result_->GetEndValue(); | 549 *end = time_stamp + elapsed_time; |
| 522 } | |
| 523 } | 550 } |
| 524 | 551 |
| 525 int64 GPUTimer::GetDeltaElapsed() { | 552 int64 GPUTimer::GetDeltaElapsed() { |
| 526 DCHECK(elapsed_timer_result_.get()); | |
| 527 DCHECK(IsAvailable()); | 553 DCHECK(IsAvailable()); |
| 528 return elapsed_timer_result_->GetDelta(); | 554 if (elapsed_timer_result_.get()) |
| 555 return elapsed_timer_result_->GetDelta(); |
| 556 return 0; |
| 529 } | 557 } |
| 530 | 558 |
| 531 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client, | 559 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client, |
| 532 bool use_elapsed_timer) | 560 bool use_elapsed_timer) |
| 533 : use_elapsed_timer_(use_elapsed_timer), | 561 : use_elapsed_timer_(use_elapsed_timer), |
| 534 gpu_timing_client_(gpu_timing_client) { | 562 gpu_timing_client_(gpu_timing_client) { |
| 535 } | 563 } |
| 536 | 564 |
| 537 GPUTimingClient::GPUTimingClient(GPUTimingImpl* gpu_timing) | 565 GPUTimingClient::GPUTimingClient(GPUTimingImpl* gpu_timing) |
| 538 : gpu_timing_(gpu_timing) { | 566 : gpu_timing_(gpu_timing) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 596 | 624 |
| 597 void GPUTimingClient::ForceTimeElapsedQuery() { | 625 void GPUTimingClient::ForceTimeElapsedQuery() { |
| 598 DCHECK(gpu_timing_); | 626 DCHECK(gpu_timing_); |
| 599 gpu_timing_->ForceTimeElapsedQuery(); | 627 gpu_timing_->ForceTimeElapsedQuery(); |
| 600 } | 628 } |
| 601 | 629 |
| 602 GPUTimingClient::~GPUTimingClient() { | 630 GPUTimingClient::~GPUTimingClient() { |
| 603 } | 631 } |
| 604 | 632 |
| 605 } // namespace gfx | 633 } // namespace gfx |
| OLD | NEW |