Chromium Code Reviews| 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() { | |
|
piman
2015/07/16 20:42:25
I think you can add a DCHECK that we're not in Wai
David Yen
2015/07/16 21:19:30
Done.
| |
| 483 time_stamp_result_ = nullptr; | |
| 484 elapsed_timer_result_ = nullptr; | |
| 485 timer_state_ = kTimerState_Ready; | |
| 486 } | |
| 487 | |
| 488 void GPUTimer::QueryTimeStamp() { | |
| 489 DCHECK(gpu_timing_client_->gpu_timing_); | |
| 490 Reset(); | |
| 491 time_stamp_result_ = gpu_timing_client_->gpu_timing_->DoTimeStampQuery(); | |
| 492 timer_state_ = kTimerState_WaitingForResult; | |
| 493 } | |
| 494 | |
| 479 void GPUTimer::Start() { | 495 void GPUTimer::Start() { |
| 480 DCHECK(gpu_timing_client_->gpu_timing_); | 496 DCHECK(gpu_timing_client_->gpu_timing_); |
| 497 Reset(); | |
| 481 if (!use_elapsed_timer_) | 498 if (!use_elapsed_timer_) |
| 482 time_stamp_result_ = gpu_timing_client_->gpu_timing_->DoTimeStampQuery(); | 499 time_stamp_result_ = gpu_timing_client_->gpu_timing_->DoTimeStampQuery(); |
| 483 | 500 |
| 484 elapsed_timer_result_ = | 501 elapsed_timer_result_ = |
| 485 gpu_timing_client_->gpu_timing_->BeginElapsedTimeQuery(); | 502 gpu_timing_client_->gpu_timing_->BeginElapsedTimeQuery(); |
| 503 timer_state_ = kTimerState_WaitingForEnd; | |
| 486 } | 504 } |
| 487 | 505 |
| 488 void GPUTimer::End() { | 506 void GPUTimer::End() { |
| 507 DCHECK(timer_state_ == kTimerState_WaitingForEnd); | |
| 489 DCHECK(elapsed_timer_result_.get()); | 508 DCHECK(elapsed_timer_result_.get()); |
| 490 end_requested_ = true; | |
| 491 gpu_timing_client_->gpu_timing_->EndElapsedTimeQuery(elapsed_timer_result_); | 509 gpu_timing_client_->gpu_timing_->EndElapsedTimeQuery(elapsed_timer_result_); |
| 510 timer_state_ = kTimerState_WaitingForResult; | |
| 492 } | 511 } |
| 493 | 512 |
| 494 bool GPUTimer::IsAvailable() { | 513 bool GPUTimer::IsAvailable() { |
| 495 if (!end_requested_) | 514 if (timer_state_ == kTimerState_WaitingForResult) { |
| 496 return false; | 515 // Elapsed timer are only used during start/end queries and always after |
| 497 if (!end_available_) { | 516 // the timestamp query. Otherwise only the timestamp is used. |
| 498 DCHECK(elapsed_timer_result_.get()); | 517 scoped_refptr<QueryResult> result = |
| 499 if (elapsed_timer_result_->IsAvailable()) { | 518 elapsed_timer_result_.get() ? |
| 500 end_available_ = true; | 519 elapsed_timer_result_ : |
| 520 time_stamp_result_; | |
| 521 | |
| 522 DCHECK(result.get()); | |
| 523 if (result->IsAvailable()) { | |
| 524 timer_state_ = kTimerState_ResultAvailable; | |
| 501 } else { | 525 } else { |
| 502 gpu_timing_client_->gpu_timing_->UpdateQueryResults(); | 526 gpu_timing_client_->gpu_timing_->UpdateQueryResults(); |
| 503 end_available_ = elapsed_timer_result_->IsAvailable(); | 527 if (result->IsAvailable()) |
| 528 timer_state_ = kTimerState_ResultAvailable; | |
| 504 } | 529 } |
| 505 } | 530 } |
| 506 return end_available_; | 531 |
| 532 return (timer_state_ == kTimerState_ResultAvailable); | |
| 507 } | 533 } |
| 508 | 534 |
| 509 void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) { | 535 void GPUTimer::GetStartEndTimestamps(int64* start, int64* end) { |
| 510 DCHECK(start && end); | 536 DCHECK(start && end); |
| 511 DCHECK(elapsed_timer_result_.get()); | 537 DCHECK(elapsed_timer_result_.get() || time_stamp_result_.get()); |
| 512 DCHECK(IsAvailable()); | 538 DCHECK(IsAvailable()); |
| 513 if (time_stamp_result_.get()) { | 539 const int64_t time_stamp = time_stamp_result_.get() ? |
| 514 DCHECK(time_stamp_result_->IsAvailable()); | 540 time_stamp_result_->GetStartValue() : |
| 515 const int64_t time_stamp = time_stamp_result_->GetStartValue(); | 541 elapsed_timer_result_->GetStartValue(); |
| 516 *start = time_stamp; | 542 const int64_t elapsed_time = elapsed_timer_result_.get() ? |
| 517 *end = time_stamp + elapsed_timer_result_->GetDelta(); | 543 elapsed_timer_result_->GetDelta() : |
| 518 } else { | 544 0; |
| 519 // Use estimation from elasped timer results. | 545 |
| 520 *start = elapsed_timer_result_->GetStartValue(); | 546 *start = time_stamp; |
| 521 *end = elapsed_timer_result_->GetEndValue(); | 547 *end = time_stamp + elapsed_time; |
| 522 } | |
| 523 } | 548 } |
| 524 | 549 |
| 525 int64 GPUTimer::GetDeltaElapsed() { | 550 int64 GPUTimer::GetDeltaElapsed() { |
| 526 DCHECK(elapsed_timer_result_.get()); | |
| 527 DCHECK(IsAvailable()); | 551 DCHECK(IsAvailable()); |
| 528 return elapsed_timer_result_->GetDelta(); | 552 if (elapsed_timer_result_.get()) |
| 553 return elapsed_timer_result_->GetDelta(); | |
| 554 return 0; | |
| 529 } | 555 } |
| 530 | 556 |
| 531 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client, | 557 GPUTimer::GPUTimer(scoped_refptr<GPUTimingClient> gpu_timing_client, |
| 532 bool use_elapsed_timer) | 558 bool use_elapsed_timer) |
| 533 : use_elapsed_timer_(use_elapsed_timer), | 559 : use_elapsed_timer_(use_elapsed_timer), |
| 534 gpu_timing_client_(gpu_timing_client) { | 560 gpu_timing_client_(gpu_timing_client) { |
| 535 } | 561 } |
| 536 | 562 |
| 537 GPUTimingClient::GPUTimingClient(GPUTimingImpl* gpu_timing) | 563 GPUTimingClient::GPUTimingClient(GPUTimingImpl* gpu_timing) |
| 538 : gpu_timing_(gpu_timing) { | 564 : gpu_timing_(gpu_timing) { |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 596 | 622 |
| 597 void GPUTimingClient::ForceTimeElapsedQuery() { | 623 void GPUTimingClient::ForceTimeElapsedQuery() { |
| 598 DCHECK(gpu_timing_); | 624 DCHECK(gpu_timing_); |
| 599 gpu_timing_->ForceTimeElapsedQuery(); | 625 gpu_timing_->ForceTimeElapsedQuery(); |
| 600 } | 626 } |
| 601 | 627 |
| 602 GPUTimingClient::~GPUTimingClient() { | 628 GPUTimingClient::~GPUTimingClient() { |
| 603 } | 629 } |
| 604 | 630 |
| 605 } // namespace gfx | 631 } // namespace gfx |
| OLD | NEW |